📄 channel.h
字号:
// ------------------------------------------------// File : channel.h// Date: 4-apr-2002// Author: giles//// (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.// ------------------------------------------------#ifndef _CHANNEL_H#define _CHANNEL_H#include "sys.h"#include "stream.h"#include "gnutella.h"#include "xml.h"#include "asf.h"
#include "cstream.h"
class AtomStream;
class ChanHitSearch;
// --------------------------------------------------struct MP3Header{ int lay; int version; int error_protection; int bitrate_index; int sampling_frequency; int padding; int extension; int mode; int mode_ext; int copyright; int original; int emphasis; int stereo;};// ----------------------------------class TrackInfo{public: void clear() { contact.clear(); title.clear(); artist.clear(); album.clear(); genre.clear(); } void convertTo(String::TYPE t) { contact.convertTo(t); title.convertTo(t); artist.convertTo(t); album.convertTo(t); genre.convertTo(t); }
bool update(TrackInfo &);
::String contact,title,artist,album,genre;};// ----------------------------------class ChanInfo{public: enum TYPE { T_UNKNOWN, T_RAW, T_MP3, T_OGG, T_OGM,
T_MOV, T_MPG, T_NSV, T_WMA, T_WMV, T_PLS, T_ASX }; enum PROTOCOL { SP_UNKNOWN, SP_PEERCAST, SP_HTTP, SP_FILE, SP_MMS,
SP_PCP }; enum STATUS { S_UNKNOWN, S_PLAY }; ChanInfo() {init();} void init(); void init(const char *); void init(const char *, GnuID &, TYPE, int); void init(XML::Node *); void initNameID(const char *);
void updateFromXML(XML::Node *); void readTrackXML(XML::Node *); void readServentXML(XML::Node *); bool update(ChanInfo &); XML::Node *createQueryXML(); XML::Node *createChannelXML(); XML::Node *createRelayChannelXML(); XML::Node *createTrackXML(); bool match(XML::Node *); bool match(ChanInfo &); bool matchNameID(ChanInfo &);
void writeInfoAtoms(AtomStream &atom);
void writeTrackAtoms(AtomStream &atom);
void readInfoAtoms(AtomStream &,int);
void readTrackAtoms(AtomStream &,int);
unsigned int getUptime(); unsigned int getAge();
bool isActive() {return id.isSet();}
bool isPrivate() {return bcID.getFlags() & 1;} static const char *getTypeStr(TYPE); static const char *getProtocolStr(PROTOCOL); static const char *getTypeExt(TYPE); static TYPE getTypeFromStr(const char *str); static PROTOCOL getProtocolFromStr(const char *str); ::String name; GnuID id,bcID; int bitrate; TYPE contentType; PROTOCOL srcProtocol; unsigned int lastPlayStart,lastPlayEnd; unsigned int numSkips;
unsigned int createdTime;
STATUS status; TrackInfo track; ::String desc,genre,url,comment;
};// ----------------------------------class ChanHit{public: void init();
void initLocal(int numl,int numr,int nums,int uptm,bool,unsigned int,unsigned int);
XML::Node *createXML();
void writeAtoms(AtomStream &,GnuID &);
bool writeVariable(Stream &, const String &);
void pickNearestIP(Host &);
Host host;
Host rhost[2]; unsigned int numListeners,numRelays,numHops; unsigned int time,upTime,lastContact;
unsigned int hitID; GnuID sessionID,chanID;
unsigned int version;
unsigned int oldestPos,newestPos;
bool firewalled:1,stable:1,tracker:1,recv:1,yp:1,dead:1,direct:1,relay:1,cin:1;
ChanHit *next;
};// ----------------------------------class ChanHitList{public: ChanHitList();
~ChanHitList();
int contactTrackers(bool,int,int,int);
ChanHit *addHit(ChanHit &); void delHit(ChanHit &);
void deadHit(ChanHit &);
int numHits(); int numListeners(); int numRelays();
int numFirewalled(); int numTrackers();
int closestHit(); int furthestHit(); unsigned int newestHit();
int pickHits(ChanHitSearch &);
bool isUsed() {return used;} int clearDeadHits(unsigned int,bool); XML::Node *createXML(bool addHits = true);
ChanHit *deleteHit(ChanHit *);
int getTotalListeners();
int getTotalRelays(); int getTotalFirewalled();
bool used;
ChanInfo info; ChanHit *hit; unsigned int lastHitTime; ChanHitList *next;
};// ----------------------------------
class ChanHitSearch
{
public:
enum
{
MAX_RESULTS = 8
};
ChanHitSearch() { init(); }
void init();
ChanHit best[MAX_RESULTS];
Host matchHost;
unsigned int waitDelay;
bool useFirewalled;
bool trackersOnly;
bool useBusyRelays,useBusyControls;
GnuID excludeID;
int numResults;
};
// ----------------------------------class ChanMeta{public: enum { MAX_DATALEN = 65536 }; void init() { len = 0; cnt = 0; startPos = 0; } void fromXML(XML &); void fromMem(void *,int); void addMem(void *,int); unsigned int len,cnt,startPos; char data[MAX_DATALEN];};// ------------------------------------------class RawStream : public ChannelStream{public:
virtual void readHeader(Stream &,Channel *);
virtual int readPacket(Stream &,Channel *);
virtual void readEnd(Stream &,Channel *);
};// ------------------------------------------class PeercastStream : public ChannelStream{public:
virtual void readHeader(Stream &,Channel *);
virtual int readPacket(Stream &,Channel *);
virtual void readEnd(Stream &,Channel *);
};// ------------------------------------------class ChannelSource{public: virtual void stream(Channel *) = 0;
virtual int getSourceRate() {return 0;}};// ------------------------------------------class PeercastSource : public ChannelSource{public:
virtual void stream(Channel *);};// ----------------------------------class Channel{public: enum STATUS { S_NONE, S_WAIT, S_CONNECTING, S_REQUESTING, S_CLOSING, S_RECEIVING, S_BROADCASTING, S_ABORT, S_SEARCHING, S_NOHOSTS, S_IDLE, S_ERROR,
S_NOTFOUND
}; enum TYPE { T_NONE, T_ALLOCATED, T_BROADCAST, T_RELAY }; enum SRC_TYPE { SRC_NONE, SRC_PEERCAST, SRC_SHOUTCAST, SRC_ICECAST, SRC_URL }; Channel(); void reset(); void endThread(); void startMP3File(char *); void startGet(); void startICY(ClientSocket *,SRC_TYPE); void startURL(const char *);
ChannelStream *createSource(); void resetPlayTime();
bool notFound()
{
return (status == S_NOTFOUND);
}
bool isPlaying() { return (status == S_RECEIVING) || (status == S_BROADCASTING); } bool isReceiving() { return (status == S_RECEIVING); } bool isBroadcasting() { return (status == S_BROADCASTING); } bool isFull(); bool checkBump(); bool checkIdle();
void sleepUntil(double); bool isActive() { return type != T_NONE; }
void connectFetch();
int handshakeFetch();
bool isIdle() {return isActive() && (status==S_IDLE);} static THREAD_PROC stream(ThreadInfo *);
void setStatus(STATUS s); const char *getSrcTypeStr() {return srcTypes[srcType];} const char *getStatusStr() {return statusMsgs[status];} const char *getName() {return info.name.cstr();} GnuID getID() {return info.id;} int getBitrate() {return info.bitrate; } void getIDStr(char *s) {info.id.toStr(s);} void getStreamPath(char *);
void broadcastTrackerUpdate(GnuID &,bool = false);
bool sendPacketUp(ChanPacket &,GnuID &,GnuID &,GnuID &);
bool writeVariable(Stream &, const String &,int);
bool acceptGIV(ClientSocket *);
void updateInfo(ChanInfo &);
int readStream(Stream &,ChannelStream *); void checkReadDelay(unsigned int); void processMp3Metadata(char *); void readHeader(); void startStream(); XML::Node *createRelayXML(bool);
void newPacket(ChanPacket &);
int localListeners();
int localRelays();
int totalListeners();
int totalRelays();
::String mount; ChanMeta insertMeta; ChanPacket headPack;
ChanPacketBuffer rawData;
ChannelStream *sourceStream;
unsigned int streamIndex;
ChanInfo info; ChanHit sourceHost;
GnuID remoteID; ::String sourceURL; bool bump,stayConnected; int icyMetaInterval; unsigned int streamPos; bool readDelay; TYPE type; ChannelSource *sourceData; SRC_TYPE srcType; MP3Header mp3Head; ThreadInfo thread;
unsigned int lastIdleTime; int status; static char *statusMsgs[],*srcTypes[]; ClientSocket *sock; ClientSocket *pushSock;
unsigned int lastTrackerUpdate;
unsigned int lastMetaUpdate;
double startTime,syncTime;
WEvent syncEvent;
Channel *next;
};// ----------------------------------class ChanMgr{public: enum {
MAX_IDLE_CHANNELS = 8, // max. number of channels that can be left idle MAX_METAINT = 8192 // must be at least smaller than ChanPacket data len (ie. about half)
};
ChanMgr();
Channel *deleteChannel(Channel *);
Channel *createChannel(ChanInfo &,const char *); Channel *findChannelByName(const char *); Channel *findChannelByIndex(int); Channel *findChannelByMount(const char *); Channel *findChannelByID(GnuID &); Channel *findChannelByNameID(ChanInfo &);
Channel *findPushChannel(int); void broadcastTrackerSettings();
void setUpdateInterval(unsigned int v);
void broadcastRelays(Servent *,int,int);
int broadcastPacketUp(ChanPacket &,GnuID &,GnuID &,GnuID &); void broadcastTrackerUpdate(GnuID &,bool = false);
bool writeVariable(Stream &, const String &,int); int findChannels(ChanInfo &,Channel **,int); int findChannelsByStatus(Channel **,int,Channel::STATUS);
int numIdleChannels(); int numChannels();
void closeOldestIdle(); void closeAll();
void quit(); void addHit(Host &,GnuID &,bool);
ChanHit *addHit(ChanHit &); void delHit(ChanHit &);
void deadHit(ChanHit &);
void setFirewalled(Host &); ChanHitList *findHitList(ChanInfo &);
ChanHitList *findHitListByID(GnuID &); ChanHitList *addHitList(ChanInfo &);
void clearHitLists(); void clearDeadHits(bool); int numHitLists(); void setBroadcastMsg(::String &); Channel *createRelay(ChanInfo &,bool); Channel *findAndRelay(ChanInfo &); void startSearch(ChanInfo &); void playChannel(ChanInfo &); void findAndPlayChannel(ChanInfo &,bool);
bool isBroadcasting(GnuID &); bool isBroadcasting();
int pickHits(ChanHitSearch &);
Channel *channel; ChanHitList *hitlist; GnuID broadcastID; ChanInfo searchInfo; int numFinds; ::String broadcastMsg;
unsigned int broadcastMsgInterval; unsigned int lastHit,lastQuery; unsigned int maxUptime; bool searchActive; unsigned int deadHitAge; int icyMetaInterval; int maxRelaysPerChannel; WLock lock; int minBroadcastTTL,maxBroadcastTTL; int pushTimeout,pushTries,maxPushHops; unsigned int autoQuery;
unsigned int prefetchTime;
unsigned int lastYPConnect;
unsigned int icyIndex;
unsigned int hostUpdateInterval; unsigned int bufferTime;
GnuID currFindAndPlayChannel;
};// ----------------------------------class PlayList{public: enum TYPE { T_NONE, T_SCPLS, T_PLS, T_ASX, T_RAM,
}; PlayList(TYPE t, int max) { maxURLs = max; numURLs = 0; type = t; urls = new ::String[max]; titles = new ::String[max]; } ~PlayList() { delete [] urls; delete [] titles; } void addURL(const char *url, const char *tit) { if (numURLs < maxURLs) { urls[numURLs].set(url); titles[numURLs].set(tit); numURLs++; } } void addChannels(const char *,Channel **,int); void addChannel(const char *,ChanInfo &); void writeSCPLS(Stream &); void writePLS(Stream &); void writeASX(Stream &); void writeRAM(Stream &);
void readSCPLS(Stream &); void readPLS(Stream &); void readASX(Stream &); void read(Stream &s) { try { switch (type) { case T_SCPLS: readSCPLS(s); break; case T_PLS: readPLS(s); break; case T_ASX: readASX(s); break; } }catch(StreamException &) {} // keep pls regardless of errors (eof isn`t handled properly in sockets) } void write(Stream &s) { switch (type) { case T_SCPLS: writeSCPLS(s); break; case T_PLS: writePLS(s); break; case T_ASX: writeASX(s); break; case T_RAM: writeRAM(s); break;
} } TYPE type; int numURLs,maxURLs; ::String *urls,*titles;};// ----------------------------------extern ChanMgr *chanMgr;#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -