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

📄 servhs.cpp

📁 这是和p2p相关的一份源码
💻 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"// -----------------------------------void Servent::handshakeHTTP(HTTP &http){	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_UNAUTHORIZED,401);			LOG_DEBUG("Admin client");			handshakeCMD(fn+7);		}else if (strncmp(fn,"/admin/?",8)==0)		{			if (!isAllowed(ALLOW_HTML))				throw HTTPException(HTTP_SC_UNAUTHORIZED,401);			LOG_DEBUG("Admin client");			handshakeCMD(fn+8);		}else if (strncmp(fn,"/admin.cgi",10)==0)		{			if (!isAllowed(ALLOW_BROADCAST))				throw HTTPException(HTTP_SC_UNAUTHORIZED,401);			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=NULL;				for(i=0; i<ChanMgr::MAX_CHANNELS; i++)				{					c = &chanMgr->channels[i];					if ((c->status == Channel::S_BROADCASTING) &&					   (c->srcType == Channel::SRC_SHOUTCAST))					{						// if we have a mount point then check for it, otherwise update all channels.						if (mountArg)							if (strcmp(c->mount,mountArg))								c = NULL;						if (c)						{							c->info.track.title.set(songArg,String::T_ESC);							if (urlArg)								if (urlArg[0])									c->info.track.contact.set(urlArg,String::T_ESC);							LOG_CHANNEL("Ch.%d Shoutcast update: %s",c->index,songArg);							c->updateMeta();						}					}				}			}		}else if (strncmp(fn,"/scpls/",7)==0)		{			ChanInfo info;			info.initNameID(fn+7);			ChanHitList *chl = chanMgr->findHitList(info);			if (chl)				handshakePLS(&chl,1,false);			else				throw HTTPException(HTTP_SC_NOTFOUND,404);		}else if (strncmp(fn,"/pls/",5)==0)		{			if (!isAllowed(ALLOW_DATA))				throw HTTPException(HTTP_SC_UNAUTHORIZED,401);			if (!servMgr->streamFull() || isPrivate())			{				LOG_NETWORK("PLS client");								if (strnicmp(fn+5,"*.pls",5)==0)				{					ChanHitList *chl[ChanMgr::MAX_HITLISTS];					int num=0;					for(int i=0; i<ChanMgr::MAX_HITLISTS; i++)						if (chanMgr->hitlists[i].isUsed())							chl[num++] = &chanMgr->hitlists[i];					handshakePLS(chl,num,false);									}else{					Channel *clist[16];					ChanInfo info;					info.initNameID(fn+5);					int num = chanMgr->findChannels(info,clist,16);					if (!num)						num = chanMgr->findAndRelay(info,clist,16);					if (num)					{						for(int i=0; i<num; i++)							clist[i]->prefetchCnt = 100;	// prefetch for 100 packets before giving up and closing channel						handshakePLS(clist,num,false);					}else						LOG_ERROR("Channel not found: %s",fn+5);				}			}else			{				throw HTTPException(HTTP_SC_UNAVAILABLE,401);			}		}else if (strncmp(fn,"/mp3/",5)==0)		{			if (!isAllowed(ALLOW_DATA))				throw HTTPException(HTTP_SC_UNAUTHORIZED,401);			triggerChannel(fn+5,ChanInfo::T_MP3,true);		}else if (strncmp(fn,"/ogg/",5)==0)		{			if (!isAllowed(ALLOW_DATA))				throw HTTPException(HTTP_SC_UNAUTHORIZED,401);			triggerChannel(fn+5,ChanInfo::T_OGG,true);		}else if (strncmp(fn,"/channel/",9)==0)		{			if (!isAllowed(ALLOW_DATA))				throw HTTPException(HTTP_SC_UNAUTHORIZED,401);			triggerChannel(fn+9,ChanInfo::T_UNKNOWN,false);		}else if (strncmp(fn,"/stream/",8)==0)		{			if (!isAllowed(ALLOW_DATA))				throw HTTPException(HTTP_SC_UNAUTHORIZED,401);			triggerChannel(fn+8,ChanInfo::T_UNKNOWN,true);		}else if (strncmp(fn,"/rtsp/",6)==0)		{			//handshakeRTSP(fn+6);		}else if (strcmp(fn,"/")==0)		{			if (!isAllowed(ALLOW_HTML))				throw HTTPException(HTTP_SC_UNAUTHORIZED,401);			LOG_NETWORK("HTML client");			handshakeCMD(fn+1);		}else{			LOG_ERROR("GET: %s",fn); 			throw HTTPException(HTTP_SC_BADREQUEST,400);		}	}else if (http.isRequest("GIV"))	{		if (!isAllowed(ALLOW_DATA))			throw HTTPException(HTTP_SC_UNAUTHORIZED,401);		char *end = strstr(in+4,":");		if (!end)			throw HTTPException(HTTP_SC_BADREQUEST,400);		*end = 0;		int index = atoi(in+4);		// 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->findPushChannel(index);		if (ch)			LOG_NETWORK("GIV %d to channel %d",index,ch->index);		else			LOG_NETWORK("GIV %d, no channels waiting",index);		if (!ch)			throw HTTPException(HTTP_SC_NOTFOUND,404);		ch->pushSock = sock;		ch->pushIndex = 0;		sock = NULL;	// release this servent but dont close socket.		}else if (http.isRequest("PEERCAST CONNECT"))	{		if (!isAllowed(ALLOW_SERVENT))			throw HTTPException(HTTP_SC_UNAUTHORIZED,401);		if (!servMgr->inFull())		{			LOG_DEBUG("PEERCAST client");			processServent();		}else{			throw HTTPException(HTTP_SC_UNAVAILABLE,503);		}	}else if (http.isRequest("GNUTELLA CONNECT"))	{		if (!isAllowed(ALLOW_SERVENT))			throw HTTPException(HTTP_SC_UNAUTHORIZED,401);		if ((servMgr->allowGnutella) && !servMgr->inFull())		{			LOG_DEBUG("GNUTELLA client");			processServent();		}else{			throw HTTPException(HTTP_SC_UNAVAILABLE,503);		}	}else if (http.isRequest("SOURCE"))	{		if (!isAllowed(ALLOW_BROADCAST))			throw HTTPException(HTTP_SC_UNAUTHORIZED,401);		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 to %s",mount?mount:"unknown");		}		if (mount)			strcpy(loginMount,mount);		handshakeICY(Channel::SRC_ICECAST);		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_UNAUTHORIZED,401);		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);		sock = NULL;	// socket is taken over by channel, so don`t close it	}else if (http.isRequest("POST"))	{		handshakePOST();	}else	{		throw HTTPException(HTTP_SC_BADREQUEST,400);	}}// -----------------------------------void Servent::handshakeIncoming(){	sock->timeout = 10000;	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);	}else	{		LOG_DEBUG("Connect from %s '%s'",sb,buf);		HTTP http(*sock);		http.initRequest(buf);		handshakeHTTP(http);	}}// -----------------------------------void Servent::triggerChannel(char *n, ChanInfo::TYPE tp, bool isRaw)	{	HTTP http(*sock);	// remove file extension (only added for winamp)	char *ext = strstr(n,".");	if (ext) *ext = 0;	Channel *ch;	ChanInfo info;	info.initNameID(n);	ch=chanMgr->findChannel(info);		// channel not in relay list, so find it hitlist	if (!ch)	{		if (!chanMgr->findAndRelay(info,&ch,1))			ch=NULL;		// should do global search here	}	if (!ch)		throw HTTPException(HTTP_SC_NOTFOUND,404);	bool isFull = servMgr->bitrateFull(ch->getBitrate()) || ch->isFull() || servMgr->streamFull();	if (!isFull || isPrivate())	{		LOG_DEBUG("Channel client: OK");		type = T_STREAM;		chanID = ch->info.id;		processStream(false,isRaw);	}else{		throw HTTPException(HTTP_SC_UNAVAILABLE,503);	}}// -----------------------------------void writePLSHeader(Stream &s){	s.writeLine(HTTP_SC_OK);	s.writeLine("%s %s",HTTP_HS_SERVER,PCX_AGENT);	s.writeLine("%s %s",HTTP_HS_CONTENT,MIME_XM3U);    s.writeLine("Content-Disposition: inline; filename=playlist.m3u");    s.writeLine("Cache-Control: private" );	s.writeLine("%s %s",HTTP_HS_CONNECTION,"close");	s.writeLine("");}// -----------------------------------void Servent::handshakePLS(Channel **cl, int num, bool doneHandshake){	char url[256];	char in[128];	if (!doneHandshake)		while (sock->readLine(in,128));	if (getLocalURL(url))	{		writePLSHeader(*sock);		PlayList *pls;		pls = new PlayList(PlayList::T_PLS,num);		pls->addChannels(url,cl,num);		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 *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;}// -----------------------------------static void termArgs(char *str){	if (str)	{		int slen = strlen(str);		for(int i=0; i<slen; i++)			if (str[i]=='&') str[i] = 0;	}}// -----------------------------------static char *nextCGIarg(char *cp, char *cmd, char *arg){	if (!*cp)		return NULL;	// fetch command	while (*cp)	{		char c = *cp++;		if (c == '=')			break;		else			*cmd++ = c;	}	*cmd = 0;	// fetch arg	while (*cp)	{		char c = *cp++;		if (c == '&')			break;		else			*arg++ = c;	}	*arg = 0;	return cp;}// -----------------------------------bool getCGIargBOOL(char *a){	return (strcmp(a,"1")==0);}// -----------------------------------int getCGIargINT(char *a){	return atoi(a);}// -----------------------------------// Warning: testing RTSP/RTP stuff below.// .. moved over to seperate app now.// -----------------------------------void Servent::handshakePOST(){#if 0	char tmp[1024];    while (sock->readLine(tmp,sizeof(tmp)))		LOG_DEBUG("POST: %s",tmp);	while (sock->active())	{		// Quicktime (6) doesnt seem to flush its buffers, so we don`t receive a proper base64 body sometimes.		// So we have to wait until theres some data pending before going ahead to read otherwise it`ll stall.		while (!sock->readPending())			sys->sleepIdle();		int rl = sock->readPending();		if (rl > sizeof(tmp)-1)			rl = sizeof(tmp)-1;		sock->read(tmp,rl);				tmp[rl]=0;		MemoryStream mem(tmp,rl);		mem.convertFromBase64();		char cmd[512],ln[512];	    mem.readLine(cmd,sizeof(cmd));		LOG_DEBUG("RTSP-CMD: %s",cmd);		if (strncmp(cmd,"DESCRIBE",8)==0)		{		    while (mem.readLine(ln,sizeof(ln)))				LOG_DEBUG("RTSP-ARG: %s",ln);#if 0			LOG_DEBUG("out");			sock->writeLine("RTSP/1.0 200 OK");			sock->writeLine("Content-Type: application/sdp");			sock->writeLine("Cache-Control: no-cache");			sock->writeLine("Content-length: 45");			sock->writeLine("Cseq:1");			sock->writeLine("");			sock->writeLine("o=StreamingServer 3241325783 1025857208000 IN IP4 192.168.1.3");			sock->writeLine("s=\test.mov");			sock->writeLine("m=audio 0 RTP/AVP 96");			sock->writeLine("b=AS:21");			sock->writeLine("");#endif			sock->writeLine("RTSP/1.0 200 OK");			sock->writeLine("Server: DSS/4.1.1 (Build/412.36; Platform/Win32)");			sock->writeLine("Cseq:");

⌨️ 快捷键说明

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