{
if (str)
{
- int slen = strlen(str);
- for(int i=0; i<slen; i++)
+ size_t slen = strlen(str);
+ for(size_t i=0; i<slen; i++)
if (str[i]=='&') str[i] = 0;
}
}
if (pwdArg && songArg)
{
- int i;
- int slen = strlen(fn);
+ size_t i;
+ size_t slen = strlen(fn);
for(i=0; i<slen; i++)
if (fn[i]=='&') fn[i] = 0;
mount[-1] = 0; // password preceeds
break;
}
- strcpy(loginPassword,in+7);
+ loginPassword.set(in+7);
- LOG_DEBUG("ICY client: %s %s",loginPassword,mount?mount:"unknown");
+ LOG_DEBUG("ICY client: %s %s",loginPassword.cstr(),mount?mount:"unknown");
}
if (mount)
- strcpy(loginMount,mount);
+ loginMount.set(mount);
handshakeICY(Channel::SRC_ICECAST,isHTTP);
sock = NULL; // socket is taken over by channel, so don`t close it
- }else if (http.isRequest(servMgr->password))
+ } else if (http.isRequest("HEAD")) // for android client
+ {
+ char *str = in + 4;
+
+ if (str = stristr(str, "/stream/"))
+ {
+ int cnt = 0;
+
+ str += 8;
+ while (*str && (('0' <= *str && *str <= '9') || ('A' <= *str && *str <= 'F') || ('a' <= *str && *str <= 'f')))
+ ++cnt, ++str;
+
+ if (cnt == 32 && !strncmp(str, ".wmv", 4))
+ {
+ // interpret "HEAD /stream/[0-9a-fA-F]{32}.wmv" as GET
+ LOG_DEBUG("INFO: interpret as GET");
+
+ char *fn = in+5;
+
+ char *pt = strstr(fn,HTTP_PROTO1);
+ if (pt)
+ pt[-1] = 0;
+
+ if (!sock->host.isLocalhost())
+ if (!isAllowed(ALLOW_DIRECT) || !isFiltered(ServFilter::F_DIRECT))
+ throw HTTPException(HTTP_SC_UNAVAILABLE,503);
+
+ triggerChannel(fn+8,ChanInfo::SP_HTTP,isPrivate());
+
+ return;
+ }
+ }
+
+ if (http.isRequest(servMgr->password))
+ {
+ if (!isAllowed(ALLOW_BROADCAST))
+ throw HTTPException(HTTP_SC_UNAVAILABLE,503);
+
+ loginPassword.set(servMgr->password); // pwd already checked
+
+ sock->writeLine("OK2");
+ sock->writeLine("icy-caps:11");
+ sock->writeLine("");
+ LOG_DEBUG("ShoutCast client");
+
+ handshakeICY(Channel::SRC_SHOUTCAST,isHTTP);
+ sock = NULL; // socket is taken over by channel, so don`t close it
+
+ }else
+ {
+ throw HTTPException(HTTP_SC_BADREQUEST,400);
+ }
+ } else if (http.isRequest(servMgr->password))
{
if (!isAllowed(ALLOW_BROADCAST))
throw HTTPException(HTTP_SC_UNAVAILABLE,503);
- strcpy(loginPassword,servMgr->password); // pwd already checked
+ loginPassword.set(servMgr->password); // pwd already checked
sock->writeLine("OK2");
sock->writeLine("icy-caps:11");
if (!isPrivate())
{
+ if (!ch->isPlaying() || ch->isFull() || ((type == T_DIRECT) && servMgr->directFull()))
+ return false;
+
+ if (!isIndexTxt(ch) && (type == T_RELAY) && (servMgr->relaysFull()))
+ return false;
+
Channel *c = chanMgr->channel;
int noRelay = 0;
unsigned int needRate = 0;
unsigned int allRate = 0;
while(c){
if (c->isPlaying()){
- allRate += c->info.bitrate * c->localRelays();
- if ((c != ch) && (c->localRelays() == 0)){
+ int nlr = c->localRelays();
+ allRate += c->info.bitrate * nlr;
+ if ((c != ch) && (nlr == 0)){
if(!isIndexTxt(c)) // for PCRaw (relay)
noRelay++;
needRate+=c->info.bitrate;
}
c = c->next;
}
- int diff = servMgr->maxRelays - servMgr->numStreams(Servent::T_RELAY,false);
+ unsigned int numRelay = servMgr->numStreams(Servent::T_RELAY,false);
+ int diff = servMgr->maxRelays - numRelay;
if (ch->localRelays()){
if (noRelay > diff){
noRelay = diff;
needRate = 0;
}
- // for PCRaw (relay) start.
- bool force_off = true;
-
- if(isIndexTxt(ch))
- force_off = false;
- // for PCRaw (relay) end.
-
LOG_DEBUG("Relay check: Max=%d Now=%d Need=%d ch=%d",
servMgr->maxBitrateOut, allRate, needRate, ch->info.bitrate);
- if ( !ch->isPlaying()
- || ch->isFull()
-// || servMgr->bitrateFull(needRate+ch->getBitrate())
- || (allRate + needRate + ch->info.bitrate > servMgr->maxBitrateOut)
- || ((type == T_RELAY) && servMgr->relaysFull() && force_off) // for PCRaw (relay) (force_off)
- || ((type == T_RELAY) && (((servMgr->numStreams(Servent::T_RELAY,false) + noRelay) >= servMgr->maxRelays)) && force_off) // for PCRaw (relay) (force_off)
- || ((type == T_DIRECT) && servMgr->directFull())
- ){
+ // if ( !ch->isPlaying()
+ // || ch->isFull()
+ // || (allRate + needRate + ch->info.bitrate > servMgr->maxBitrateOut)
+ // || ((type == T_RELAY) && servMgr->relaysFull() && force_off) // for PCRaw (relay) (force_off)
+ // || ((type == T_RELAY) && (((servMgr->numStreams(Servent::T_RELAY,false) + noRelay) >= servMgr->maxRelays)) && force_off) // for PCRaw (relay) (force_off)
+ // || ((type == T_DIRECT) && servMgr->directFull())
+ // ){
+
+ if (allRate + needRate + ch->info.bitrate > servMgr->maxBitrateOut)
+ {
+ LOG_DEBUG("Relay check: NG");
+ return false;
+ }
+
+ if (!isIndexTxt(ch) && (type == T_RELAY) && (numRelay + noRelay >= servMgr->maxRelays))
+ {
LOG_DEBUG("Relay check: NG");
return false;
}
{
case ServMgr::AUTH_HTTPBASIC:
if (http.isHeader("Authorization"))
- http.getAuthUserPass(user,pass);
+ http.getAuthUserPass(user, pass, sizeof(user), sizeof(pass));
break;
case ServMgr::AUTH_COOKIE:
if (http.isHeader("Cookie"))
int newPort=servMgr->serverHost.port;
int enableGetName = 0;
int allowConnectPCST = 0;
+ int disableAutoBumpIfDirect = 0; //JP-MOD
+ int asxDetailedMode = 0; //JP-MOD
char *cp = cmd;
while (cp=nextCGIarg(cp,curr,arg))
{
+ LOG_DEBUG("ARG: %s = %s", curr, arg);
+
// server
if (strcmp(curr,"serveractive")==0)
servMgr->autoServe = getCGIargBOOL(arg);
{
servMgr->numFilters++;
servMgr->filters[servMgr->numFilters].init(); // clear new entry
+ LOG_DEBUG("numFilters = %d", servMgr->numFilters);
}
}else if (strncmp(fs,"bn",2)==0)
else if (strcmp(curr, "maxRelaysIndexTxt") ==0) // for PCRaw (relay)
servMgr->maxRelaysIndexTxt = getCGIargINT(arg);
+ else if (strcmp(curr, "disableAutoBumpIfDirect") ==0) //JP-MOD
+ disableAutoBumpIfDirect = atoi(arg) ? 1 : 0;
+ else if (strcmp(curr, "asxDetailedMode") ==0) //JP-MOD
+ asxDetailedMode = getCGIargINT(arg);
}
servMgr->allowServer2 = allowServer2;
servMgr->enableGetName = enableGetName;
servMgr->allowConnectPCST = allowConnectPCST;
+ servMgr->disableAutoBumpIfDirect = disableAutoBumpIfDirect; //JP-MOD
+ servMgr->asxDetailedMode = asxDetailedMode; //JP-MOD
if (!(servMgr->allowServer1 & ALLOW_HTML) && !(servMgr->allowServer2 & ALLOW_HTML))
servMgr->allowServer1 |= ALLOW_HTML;
}else if (strcmp(curr,"type")==0)
{
info.contentType = ChanInfo::getTypeFromStr(arg);
+ }else if (strcmp(curr,"bcstClap")==0) //JP-MOD
+ {
+ info.ppFlags |= ServMgr::bcstClap;
}
}
Channel *c = chanMgr->findChannelByName(chname.cstr());
if (c && (c->isActive()) && (c->status == Channel::S_BROADCASTING)){
ChanInfo newInfo = c->info;
+ newInfo.ppFlags = ServMgr::bcstNone; //JP-MOD
while (cmd=nextCGIarg(cmd,curr,arg))
{
String chmeta;
newInfo.genre = chmeta.cstr();
else if (strcmp(curr,"comment")==0)
newInfo.comment = chmeta.cstr();
+ else if (strcmp(curr,"bcstClap")==0) //JP-MOD
+ newInfo.ppFlags |= ServMgr::bcstClap;
else if (strcmp(curr,"t_contact")==0)
newInfo.track.contact = chmeta.cstr();
else if (strcmp(curr,"t_title")==0)
rn->add(hc);
+ // calculate content-length
+ DummyStream ds;
+ xml.write(ds);
+
+ // set line-feed code to CRLF (for HTTP header)
+ bool bWriteCRLF = sock->writeCRLF;
+ sock->writeCRLF = true;
+
+ // write HTTP response header
sock->writeLine(HTTP_SC_OK);
sock->writeLineF("%s %s",HTTP_HS_SERVER,PCX_AGENT);
sock->writeLineF("%s %s",HTTP_HS_CONTENT,MIME_XML);
+ sock->writeLineF("%s %d", HTTP_HS_LENGTH, ds.getLength());
sock->writeLine("Connection: close");
-
sock->writeLine("");
+ // revert setting
+ sock->writeCRLF = bWriteCRLF;
+
+ // write HTTP body
xml.write(*sock);
}
// -----------------------------------
-void Servent::readICYHeader(HTTP &http, ChanInfo &info, char *pwd)
+void Servent::readICYHeader(HTTP &http, ChanInfo &info, char *pwd, size_t szPwd)
{
char *arg = http.getArgStr();
if (!arg) return;
info.desc.convertTo(String::T_UNICODE);
}else if (http.isHeader("Authorization"))
- http.getAuthUserPass(NULL,pwd);
+ http.getAuthUserPass(NULL, pwd, 0, sizeof(pwd));
else if (http.isHeader(PCX_HS_CHANNELID))
info.id.fromStr(arg);
else if (http.isHeader("ice-password"))
while (http.nextHeader())
{
LOG_DEBUG("ICY %s",http.cmdLine);
- readICYHeader(http,info,loginPassword);
+ readICYHeader(http, info, loginPassword.cstr(), loginPassword.MAX_LEN);
}
// check password before anything else, if needed
- if (strcmp(servMgr->password,loginPassword)!=0)
+ if (!loginPassword.isSame(servMgr->password))
{
- if (!sock->host.isLocalhost() || strlen(loginPassword))
+ if (!sock->host.isLocalhost() || !loginPassword.isEmpty())
throw HTTPException(HTTP_SC_UNAUTHORIZED,401);
}
info.id = chanMgr->broadcastID;
- info.id.encode(NULL,info.name.cstr(),loginMount,info.bitrate);
+ info.id.encode(NULL,info.name.cstr(),loginMount.cstr(),info.bitrate);
LOG_DEBUG("Incoming source: %s : %s",info.name.cstr(),ChanInfo::getTypeStr(info.contentType));
info.comment = chanMgr->broadcastMsg;
info.bcID = chanMgr->broadcastID;
- c = chanMgr->createChannel(info,loginMount);
+ c = chanMgr->createChannel(info,loginMount.cstr());
if (!c)
throw HTTPException(HTTP_SC_UNAVAILABLE,503);