OSDN Git Service

WebGUIのレスポンスが悪かったのを修正
[peercast-im/PeerCastIM.git] / c: / Git / PeerCast.root / PeerCast / core / common / servhs.cpp
index 8e352bf..192658e 100644 (file)
@@ -38,8 +38,8 @@ static void termArgs(char *str)
 {
        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;
        }
 }
@@ -162,8 +162,8 @@ void Servent::handshakeHTTP(HTTP &http, bool isHTTP)
 
                        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;
 
@@ -371,23 +371,75 @@ void Servent::handshakeHTTP(HTTP &http, bool isHTTP)
                                        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");
@@ -414,14 +466,21 @@ bool Servent::canStream(Channel *ch)
 
        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;
@@ -429,7 +488,8 @@ bool Servent::canStream(Channel *ch)
                        }
                        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;
@@ -439,23 +499,24 @@ bool Servent::canStream(Channel *ch)
                        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;
                }
@@ -717,7 +778,7 @@ bool Servent::handshakeAuth(HTTP &http,const char *args,bool local)
                {
                        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"))
@@ -921,10 +982,14 @@ void Servent::handshakeCMD(char *cmd)
                                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);
@@ -1001,6 +1066,7 @@ void Servent::handshakeCMD(char *cmd)
                                                                {
                                                                        servMgr->numFilters++;
                                                                        servMgr->filters[servMgr->numFilters].init();   // clear new entry
+                                                                       LOG_DEBUG("numFilters = %d", servMgr->numFilters);
                                                                }
 
                                                        }else if (strncmp(fs,"bn",2)==0)
@@ -1101,6 +1167,10 @@ void Servent::handshakeCMD(char *cmd)
 
                                        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);
                                }
 
 
@@ -1110,6 +1180,8 @@ void Servent::handshakeCMD(char *cmd)
                                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;
 
@@ -1190,6 +1262,9 @@ void Servent::handshakeCMD(char *cmd)
                                        }else if (strcmp(curr,"type")==0)
                                        {
                                                info.contentType = ChanInfo::getTypeFromStr(arg);
+                                       }else if (strcmp(curr,"bcstClap")==0) //JP-MOD
+                                       {
+                                               info.ppFlags |= ServMgr::bcstClap;
                                        }
 
                                }
@@ -1505,6 +1580,7 @@ void Servent::handshakeCMD(char *cmd)
                                                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;
@@ -1518,6 +1594,8 @@ void Servent::handshakeCMD(char *cmd)
                                                                        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)
@@ -1671,18 +1749,31 @@ void Servent::handshakeXML()
        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;
@@ -1707,7 +1798,7 @@ void Servent::readICYHeader(HTTP &http, ChanInfo &info, char *pwd)
                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"))
@@ -1778,15 +1869,15 @@ void Servent::handshakeICY(Channel::SRC_TYPE type, bool isHTTP)
        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);
        }
 
@@ -1800,7 +1891,7 @@ void Servent::handshakeICY(Channel::SRC_TYPE type, bool isHTTP)
 
 
        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));
 
@@ -1821,7 +1912,7 @@ void Servent::handshakeICY(Channel::SRC_TYPE type, bool isHTTP)
        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);