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

📄 servhs.cpp

📁 P2P应用 : Peercast的源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// ------------------------------------------------// File : servhs.cpp// Date: 4-apr-2002// Author: giles// Desc: //		Servent handshaking, TODO: should be in its own class//// (c) 2002 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 <stdlib.h>#include "servent.h"#include "servmgr.h"#include "html.h"#include "stats.h"#include "peercast.h"#include "pcp.h"
#include "version2.h"
// -----------------------------------static void termArgs(char *str){	if (str)	{		int slen = strlen(str);		for(int i=0; i<slen; i++)			if (str[i]=='&') str[i] = 0;	}}// -----------------------------------char *nextCGIarg(char *cp, char *cmd, char *arg){	if (!*cp)		return NULL;
	int cnt=0;
	// fetch command	while (*cp)	{		char c = *cp++;		if (c == '=')			break;		else			*cmd++ = c;

		cnt++;
		if (cnt >= (MAX_CGI_LEN-1))
			break;	}	*cmd = 0;
	cnt=0;	// fetch arg	while (*cp)	{		char c = *cp++;		if (c == '&')			break;		else			*arg++ = c;

		cnt++;
		if (cnt >= (MAX_CGI_LEN-1))
			break;	}	*arg = 0;	return cp;}// -----------------------------------bool getCGIargBOOL(char *a){	return (strcmp(a,"1")==0);}// -----------------------------------int getCGIargINT(char *a){	return atoi(a);}// -----------------------------------void Servent::handshakeHTTP(HTTP &http, bool isHTTP){	char *in = http.cmdLine;	if (http.isRequest("GET /"))	{		char *fn = in+4;		char *pt = strstr(fn,HTTP_PROTO1);		if (pt)			pt[-1] = 0;		if (strncmp(fn,"/admin?",7)==0)		{			if (!isAllowed(ALLOW_HTML))				throw HTTPException(HTTP_SC_UNAVAILABLE,503);
			LOG_DEBUG("Admin client");			handshakeCMD(fn+7);

		}else if (strncmp(fn,"/http/",6)==0)
		{
			String dirName = fn+6;

			if (!isAllowed(ALLOW_HTML))
				throw HTTPException(HTTP_SC_UNAVAILABLE,503);			

			if (!handshakeAuth(http,fn,false))
				throw HTTPException(HTTP_SC_UNAUTHORIZED,401);			


			handshakeRemoteFile(dirName);


		}else if (strncmp(fn,"/html/",6)==0)
		{
			String dirName = fn+1;

			if (!isAllowed(ALLOW_HTML))
				throw HTTPException(HTTP_SC_UNAVAILABLE,503);

			if (handshakeAuth(http,fn,true))
				handshakeLocalFile(dirName);

		}else if (strncmp(fn,"/admin/?",8)==0)		{			if (!isAllowed(ALLOW_HTML))				throw HTTPException(HTTP_SC_UNAVAILABLE,503);
			LOG_DEBUG("Admin client");			handshakeCMD(fn+8);		}else if (strncmp(fn,"/admin.cgi",10)==0)		{			if (!isAllowed(ALLOW_BROADCAST))				throw HTTPException(HTTP_SC_UNAVAILABLE,503);
			char *pwdArg = getCGIarg(fn,"pass=");			char *songArg = getCGIarg(fn,"song=");			char *mountArg = getCGIarg(fn,"mount=");			char *urlArg = getCGIarg(fn,"url=");			if (pwdArg && songArg)			{				int i;				int slen = strlen(fn);				for(i=0; i<slen; i++)					if (fn[i]=='&') fn[i] = 0;				Channel *c=chanMgr->channel;				while (c)				{					if ((c->status == Channel::S_BROADCASTING) &&					   (c->info.contentType == ChanInfo::T_MP3) )					{						// if we have a mount point then check for it, otherwise update all channels.

						bool match=true;

						if (mountArg)
							match = strcmp(c->mount,mountArg)==0;

						if (match)
						{							ChanInfo newInfo = c->info;							newInfo.track.title.set(songArg,String::T_ESC);
							newInfo.track.title.convertTo(String::T_UNICODE);							if (urlArg)								if (urlArg[0])									newInfo.track.contact.set(urlArg,String::T_ESC);							LOG_CHANNEL("Channel Shoutcast update: %s",songArg);							c->updateInfo(newInfo);
						}					}
					c=c->next;				}			}		}else if (strncmp(fn,"/pls/",5)==0)		{

			if (!sock->host.isLocalhost())
				if (!isAllowed(ALLOW_DIRECT) || !isFiltered(ServFilter::F_DIRECT))
					throw HTTPException(HTTP_SC_UNAVAILABLE,503);

			
			ChanInfo info;
			if (servMgr->getChannel(fn+5,info,isPrivate()))				handshakePLS(info,false);
			else
				throw HTTPException(HTTP_SC_NOTFOUND,404);
		}else if (strncmp(fn,"/stream/",8)==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());
					}else if (strncmp(fn,"/channel/",9)==0)		{
			if (!sock->host.isLocalhost())
				if (!isAllowed(ALLOW_NETWORK) || !isFiltered(ServFilter::F_NETWORK))
					throw HTTPException(HTTP_SC_UNAVAILABLE,503);
			triggerChannel(fn+9,ChanInfo::SP_PCP,false);
		}else 
		{
			while (http.nextHeader());
			http.writeLine(HTTP_SC_FOUND);
			http.writeLineF("Location: /%s/index.html",servMgr->htmlPath);
			http.writeLine("");
		}	}else if (http.isRequest("GIV"))	{
		HTTP http(*sock);
	
		while (http.nextHeader()) ;

		if (!isAllowed(ALLOW_NETWORK))
			throw HTTPException(HTTP_SC_UNAVAILABLE,503);

		GnuID id;
		id.clear();

		char *idstr = strstr(in,"/");
		if (idstr)
			id.fromStr(idstr+1);

		char ipstr[64];
		sock->host.toStr(ipstr);

		if (id.isSet())
		{
			// at the moment we don`t really care where the GIV came from, so just give to chan. no. if its waiting.			Channel *ch = chanMgr->findChannelByID(id);			if (!ch)
				throw HTTPException(HTTP_SC_NOTFOUND,404);

			if (!ch->acceptGIV(sock))
				throw HTTPException(HTTP_SC_UNAVAILABLE,503);

		
			LOG_DEBUG("Accepted GIV channel %s from: %s",idstr,ipstr);

			sock=NULL;					// release this servent but dont close socket.	
		}else 
		{

			if (!servMgr->acceptGIV(sock))
				throw HTTPException(HTTP_SC_UNAVAILABLE,503);

			LOG_DEBUG("Accepted GIV PCP from: %s",ipstr);
			sock=NULL;					// release this servent but dont close socket.	
		}
	}else if (http.isRequest(PCX_PCP_CONNECT))
	{

		if (!isAllowed(ALLOW_NETWORK) || !isFiltered(ServFilter::F_NETWORK))
			throw HTTPException(HTTP_SC_UNAVAILABLE,503);
		
		processIncomingPCP(true);
	}else if (http.isRequest("PEERCAST CONNECT"))
	{		if (!isAllowed(ALLOW_NETWORK) || !isFiltered(ServFilter::F_NETWORK))
			throw HTTPException(HTTP_SC_UNAVAILABLE,503);
		LOG_DEBUG("PEERCAST client");		processServent();	}else if (http.isRequest("SOURCE"))	{		if (!isAllowed(ALLOW_BROADCAST))
			throw HTTPException(HTTP_SC_UNAVAILABLE,503);
		char *mount = NULL;		char *ps;		if (ps=strstr(in,"ICE/1.0"))		{			mount = in+7;			*ps = 0;			LOG_DEBUG("ICE 1.0 client to %s",mount?mount:"unknown");		}else{			mount = in+strlen(in);			while (*--mount)				if (*mount == '/')				{					mount[-1] = 0; // password preceeds					break;				}			strcpy(loginPassword,in+7);						LOG_DEBUG("ICY client: %s %s",loginPassword,mount?mount:"unknown");		}		if (mount)			strcpy(loginMount,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))	{		if (!isAllowed(ALLOW_BROADCAST))			throw HTTPException(HTTP_SC_UNAVAILABLE,503);
		strcpy(loginPassword,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);	}}// -----------------------------------
bool Servent::canStream(Channel *ch)
{
	if (ch==NULL)
		return false;

	if (servMgr->isDisabled)
		return false;

	if (!isPrivate())
	{
		if  (
				servMgr->bitrateFull(ch->getBitrate())
				|| ((type == T_RELAY) && servMgr->relaysFull())
				|| ((type == T_DIRECT) && servMgr->directFull())
				|| !ch->isPlaying()
				|| ch->isFull()
			)
			return false;
	}

	return true;
}
// -----------------------------------void Servent::handshakeIncoming(){	setStatus(S_HANDSHAKE);	char buf[1024];	sock->readLine(buf,sizeof(buf));	char sb[64];	sock->host.toStr(sb);	if (stristr(buf,RTSP_PROTO1))	{		LOG_DEBUG("RTSP from %s '%s'",sb,buf);		RTSP rtsp(*sock);		rtsp.initRequest(buf);		handshakeRTSP(rtsp);	}else if (stristr(buf,HTTP_PROTO1))	{		LOG_DEBUG("HTTP from %s '%s'",sb,buf);		HTTP http(*sock);		http.initRequest(buf);		handshakeHTTP(http,true);	}else	{		LOG_DEBUG("Connect from %s '%s'",sb,buf);		HTTP http(*sock);		http.initRequest(buf);		handshakeHTTP(http,false);	}}// -----------------------------------void Servent::triggerChannel(char *str, ChanInfo::PROTOCOL proto,bool relay)	{
	ChanInfo info;

	servMgr->getChannel(str,info,relay);

	if (proto == ChanInfo::SP_PCP)
		type = T_RELAY;
	else
		type = T_DIRECT;

	outputProtocol = proto;

	processStream(false,info);

}// -----------------------------------void writePLSHeader(Stream &s, PlayList::TYPE type){	s.writeLine(HTTP_SC_OK);	s.writeLineF("%s %s",HTTP_HS_SERVER,PCX_AGENT);	const char *content;	switch(type)	{		case PlayList::T_PLS:			content = MIME_XM3U;			break;		case PlayList::T_ASX:			content = MIME_ASX;			break;		case PlayList::T_RAM:
			content = MIME_RAM;
			break;
		default:			content = MIME_TEXT;			break;	}	s.writeLineF("%s %s",HTTP_HS_CONTENT,content);    s.writeLine("Content-Disposition: inline");    s.writeLine("Cache-Control: private" );	s.writeLineF("%s %s",HTTP_HS_CONNECTION,"close");	s.writeLine("");}// -----------------------------------void Servent::handshakePLS(ChanInfo &info, bool doneHandshake){	char url[256];	char in[128];	if (!doneHandshake)		while (sock->readLine(in,128));
	if (getLocalURL(url))	{		PlayList::TYPE type;		if ((info.contentType == ChanInfo::T_WMA) || (info.contentType == ChanInfo::T_WMV))			type = PlayList::T_ASX;		else if (info.contentType == ChanInfo::T_OGM)
			type = PlayList::T_RAM;
		else			type = PlayList::T_PLS;		writePLSHeader(*sock,type);		PlayList *pls;		pls = new PlayList(type,1);		pls->addChannel(url,info);		pls->write(*sock);		delete pls;	}}// -----------------------------------void Servent::handshakePLS(ChanHitList **cl, int num, bool doneHandshake){	char url[256];	char in[128];	if (!doneHandshake)		while (sock->readLine(in,128));	if (getLocalURL(url))	{		writePLSHeader(*sock,PlayList::T_SCPLS);		PlayList *pls;		pls = new PlayList(PlayList::T_SCPLS,num);		for(int i=0; i<num; i++)			pls->addChannel(url,cl[i]->info);		pls->write(*sock);		delete pls;	}}// -----------------------------------bool Servent::getLocalURL(char *str){	if (!sock)		throw StreamException("Not connected");	char ipStr[64];	Host h;		if (sock->host.localIP())		h = sock->getLocalHost();	else		h = servMgr->serverHost;	h.port = servMgr->serverHost.port;	h.toStr(ipStr);	sprintf(str,"http://%s",ipStr);				return true;}// -----------------------------------// Warning: testing RTSP/RTP stuff below.// .. moved over to seperate app now.// -----------------------------------void Servent::handshakePOST(){	char tmp[1024];    while (sock->readLine(tmp,sizeof(tmp)))		LOG_DEBUG("POST: %s",tmp);	throw HTTPException(HTTP_SC_BADREQUEST,400);}// -----------------------------------void Servent::handshakeRTSP(RTSP &rtsp){	throw HTTPException(HTTP_SC_BADREQUEST,400);}// -----------------------------------
bool Servent::handshakeAuth(HTTP &http,const char *args,bool local)

⌨️ 快捷键说明

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