OSDN Git Service

d6f0c479d5e996ab5e9820926c5871fd4a8b399f
[peercast-im/PeerCastIM.git] / PeerCast.root / PeerCast / core / common / channel.h
1 // ------------------------------------------------
2 // File : channel.h
3 // Date: 4-apr-2002
4 // Author: giles
5 //
6 // (c) 2002 peercast.org
7 // ------------------------------------------------
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
12
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 // ------------------------------------------------
18
19 #ifndef _CHANNEL_H
20 #define _CHANNEL_H
21
22 #include "sys.h"
23 #include "stream.h"
24 #include "gnutella.h"
25 #include "xml.h"
26 #include "asf.h"
27 #include "cstream.h"
28
29 class AtomStream;
30 class ChanHitSearch;
31
32 // --------------------------------------------------
33 struct MP3Header
34 {
35         int lay;
36         int version;
37         int error_protection;
38         int bitrate_index;
39         int sampling_frequency;
40         int padding;
41         int extension;
42         int mode;
43         int mode_ext;
44         int copyright;
45         int original;
46         int emphasis;
47         int stereo;
48 };
49
50 // ----------------------------------
51 class TrackInfo
52 {
53 public:
54         void    clear()
55         {
56                 contact.clear();
57                 title.clear();
58                 artist.clear();
59                 album.clear();
60                 genre.clear();
61         }
62
63         void    convertTo(String::TYPE t)
64         {
65                 contact.convertTo(t);
66                 title.convertTo(t);
67                 artist.convertTo(t);
68                 album.convertTo(t);
69                 genre.convertTo(t);
70         }
71
72         bool    update(TrackInfo &);
73
74         ::String        contact,title,artist,album,genre;
75 };
76
77
78
79 // ----------------------------------
80 class ChanInfo
81 {
82 public:
83         enum TYPE
84         {
85                 T_UNKNOWN,
86
87                 T_RAW,
88                 T_MP3,
89                 T_OGG,
90                 T_OGM,
91                 T_MOV,
92                 T_MPG,
93                 T_NSV,
94
95                 T_WMA,
96                 T_WMV,
97
98                 T_PLS,
99                 T_ASX
100         };
101
102
103         enum PROTOCOL
104         {
105                 SP_UNKNOWN,
106                 SP_PEERCAST,
107                 SP_HTTP,
108                 SP_FILE,
109                 SP_MMS,
110                 SP_PCP
111         };
112
113
114         enum STATUS
115         {
116                 S_UNKNOWN,
117                 S_PLAY
118         };
119
120         ChanInfo() {init();}
121
122         void    init();
123         void    init(const char *);
124         void    init(const char *, GnuID &, TYPE, int);
125         void    init(XML::Node *);
126         void    initNameID(const char *);
127
128         void    updateFromXML(XML::Node *);
129
130         void    readTrackXML(XML::Node *);
131         void    readServentXML(XML::Node *);
132         bool    update(ChanInfo &);
133         XML::Node *createQueryXML();
134         XML::Node *createChannelXML();
135         XML::Node *createRelayChannelXML();
136         XML::Node *createTrackXML();
137         bool    match(XML::Node *);
138         bool    match(ChanInfo &);
139         bool    matchNameID(ChanInfo &);
140
141         void    writeInfoAtoms(AtomStream &atom);
142         void    writeTrackAtoms(AtomStream &atom);
143
144         void    readInfoAtoms(AtomStream &,int);
145         void    readTrackAtoms(AtomStream &,int);
146
147         unsigned int getUptime();
148         unsigned int getAge();
149         bool    isActive() {return id.isSet();}
150         bool    isPrivate() {return bcID.getFlags() & 1;}
151         static  const   char *getTypeStr(TYPE);
152         static  const   char *getProtocolStr(PROTOCOL);
153         static  const   char *getTypeExt(TYPE);
154         static  TYPE            getTypeFromStr(const char *str);
155         static  PROTOCOL        getProtocolFromStr(const char *str);
156
157         ::String        name;
158         GnuID   id,bcID;
159         int             bitrate;
160         TYPE    contentType;
161         PROTOCOL        srcProtocol;
162         unsigned int lastPlayStart,lastPlayEnd;
163         unsigned int numSkips;
164         unsigned int createdTime;
165
166         STATUS  status;
167
168         TrackInfo       track;
169         ::String        desc,genre,url,comment;
170
171 };
172
173
174 // ----------------------------------
175 class ChanHit
176 {
177 public:
178         void    init();
179         void    initLocal(int numl,int numr,int nums,int uptm,bool,bool,unsigned int,Channel*,unsigned int,unsigned int);
180         XML::Node *createXML();
181
182         void    writeAtoms(AtomStream &,GnuID &);
183         bool    writeVariable(Stream &, const String &);
184
185         void    pickNearestIP(Host &);
186
187         Host                            host;
188         Host                            rhost[2];
189         unsigned int            numListeners,numRelays,numHops;
190         unsigned int            time,upTime,lastContact;
191         unsigned int            hitID;
192         GnuID                           sessionID,chanID;
193         unsigned int            version;
194         unsigned int            version_vp;
195
196         bool    firewalled:1,stable:1,tracker:1,recv:1,yp:1,dead:1,direct:1,relay:1,cin:1;
197         bool    relayfull:1,chfull:1,ratefull:1;
198
199         ChanHit *next;
200
201         int status;
202         int servent_id;
203
204         unsigned int            oldestPos,newestPos;
205         Host uphost;
206         unsigned int            uphostHops;
207
208         char                            version_ex_prefix[2];
209         unsigned int            version_ex_number;
210
211         unsigned int lastSendSeq;
212 };
213 // ----------------------------------
214 class ChanHitList
215 {
216 public:
217         ChanHitList();
218         ~ChanHitList();
219
220         int             contactTrackers(bool,int,int,int);
221
222         ChanHit *addHit(ChanHit &);
223         void    delHit(ChanHit &);
224         void    deadHit(ChanHit &);
225         void    clearHits(bool);
226         int             numHits();
227         int             numListeners();
228         int             numRelays();
229         int             numFirewalled();
230         int             numTrackers();
231         int             closestHit();
232         int             furthestHit();
233         unsigned int            newestHit();
234
235         int                     pickHits(ChanHitSearch &);
236         int                     pickSourceHits(ChanHitSearch &);
237
238         bool    isUsed() {return used;}
239         int             clearDeadHits(unsigned int,bool);
240         XML::Node *createXML(bool addHits = true);
241
242         ChanHit *deleteHit(ChanHit *);
243
244         int             getTotalListeners();
245         int             getTotalRelays();
246         int             getTotalFirewalled();
247
248         bool    used;
249         ChanInfo        info;
250         ChanHit *hit;
251         unsigned int lastHitTime;
252         ChanHitList *next;
253
254
255 };
256 // ----------------------------------
257 class ChanHitSearch
258 {
259 public:
260         enum
261         {
262                 MAX_RESULTS = 8
263         };
264
265         ChanHitSearch() { init(); }
266         void init();
267
268         ChanHit best[MAX_RESULTS];
269         Host    matchHost;
270         unsigned int waitDelay;
271         bool    useFirewalled;
272         bool    trackersOnly;
273         bool    useBusyRelays,useBusyControls;
274         GnuID   excludeID;
275         int             numResults;
276         unsigned int seed;
277
278         int getRelayHost(Host host1, Host host2, GnuID exID, ChanHitList *chl);
279 };
280
281 // ----------------------------------
282 class ChanMeta
283 {
284 public:
285         enum {
286                 MAX_DATALEN = 65536
287         };
288
289         void    init()
290         {
291                 len = 0;
292                 cnt = 0;
293                 startPos = 0;
294         }
295
296         void    fromXML(XML &);
297         void    fromMem(void *,int);
298         void    addMem(void *,int);
299
300         unsigned int len,cnt,startPos;
301         char    data[MAX_DATALEN];
302 };
303
304
305
306 // ------------------------------------------
307 class RawStream : public ChannelStream
308 {
309 public:
310         virtual void readHeader(Stream &,Channel *);
311         virtual int readPacket(Stream &,Channel *);
312         virtual void readEnd(Stream &,Channel *);
313
314 };
315
316 // ------------------------------------------
317 class PeercastStream : public ChannelStream
318 {
319 public:
320         virtual void readHeader(Stream &,Channel *);
321         virtual int  readPacket(Stream &,Channel *);
322         virtual void readEnd(Stream &,Channel *);
323 };
324
325 // ------------------------------------------
326 class ChannelSource
327 {
328 public:
329         virtual ~ChannelSource() {}
330         virtual void stream(Channel *) = 0;
331
332         virtual int getSourceRate() {return 0;}
333
334 };
335 // ------------------------------------------
336 class PeercastSource : public ChannelSource
337 {
338 public:
339
340
341         virtual void stream(Channel *);
342
343 };
344
345
346 // ----------------------------------
347 class Channel
348 {
349 public:
350         
351         enum STATUS
352         {
353                 S_NONE,
354                 S_WAIT,
355                 S_CONNECTING,
356                 S_REQUESTING,
357                 S_CLOSING,
358                 S_RECEIVING,
359                 S_BROADCASTING,
360                 S_ABORT,
361                 S_SEARCHING,
362                 S_NOHOSTS,
363                 S_IDLE,
364                 S_ERROR,
365                 S_NOTFOUND
366         };
367
368         enum TYPE
369         {
370                 T_NONE,
371                 T_ALLOCATED,
372                 T_BROADCAST,
373                 T_RELAY
374         };
375
376         enum SRC_TYPE
377         {
378                 SRC_NONE,
379                 SRC_PEERCAST,
380                 SRC_SHOUTCAST,
381                 SRC_ICECAST,
382                 SRC_URL
383         };
384
385
386         Channel();
387         void    reset();
388         void    endThread(bool flg);
389
390         void    startMP3File(char *);
391         void    startGet();
392         void    startICY(ClientSocket *,SRC_TYPE);
393         void    startURL(const char *);
394
395
396         ChannelStream   *createSource();
397
398         void    resetPlayTime();
399
400         bool    notFound()
401         {
402                 return (status == S_NOTFOUND);
403         }
404
405         bool    isPlaying()
406         {
407                 return (status == S_RECEIVING) || (status == S_BROADCASTING);
408         }
409
410         bool    isReceiving()
411         {
412                 return (status == S_RECEIVING);
413         }
414
415         bool    isBroadcasting()
416         {
417                 return (status == S_BROADCASTING);
418         }
419
420         bool    isFull();
421
422         bool    checkBump();
423
424         bool    checkIdle();
425         void    sleepUntil(double);
426
427         bool    isActive()
428         {
429                 return type != T_NONE;
430         }
431
432
433         void    connectFetch();
434         int             handshakeFetch();
435
436         bool    isIdle() {return isActive() && (status==S_IDLE);}
437
438         static THREAD_PROC      stream(ThreadInfo *);
439
440         static THREAD_PROC  waitFinish(ThreadInfo *);
441
442         void    setStatus(STATUS s);
443         const char  *getSrcTypeStr() {return srcTypes[srcType];}
444         const char      *getStatusStr() {return statusMsgs[status];}
445         const char      *getName() {return info.name.cstr();}
446         GnuID   getID() {return info.id;}
447         int             getBitrate() {return info.bitrate; }
448         void    getIDStr(char *s) {info.id.toStr(s);}
449         void    getStreamPath(char *);
450
451         void    broadcastTrackerUpdate(GnuID &,bool = false);
452         bool    sendPacketUp(ChanPacket &,GnuID &,GnuID &,GnuID &);
453
454         bool    writeVariable(Stream &, const String &,int);
455
456         bool    acceptGIV(ClientSocket *);
457
458         void    updateInfo(ChanInfo &);
459
460         int             readStream(Stream &,ChannelStream *);
461         
462         void    checkReadDelay(unsigned int);
463
464         void    processMp3Metadata(char *);
465
466         void    readHeader();
467
468         void    startStream();
469
470         XML::Node *createRelayXML(bool);
471
472         void    newPacket(ChanPacket &);
473
474         int             localListeners();
475         int             localRelays();
476
477         int             totalListeners();
478         int             totalRelays();
479
480         ::String mount;
481         ChanMeta        insertMeta;
482         ChanPacket      headPack;
483
484         ChanPacketBuffer        rawData;
485
486         ChannelStream *sourceStream;
487         unsigned int streamIndex;
488         
489
490         ChanInfo        info;
491         ChanHit         sourceHost;
492
493         GnuID           remoteID;
494
495
496         ::String  sourceURL;
497
498         bool    bump,stayConnected;
499         int             icyMetaInterval;
500         unsigned int streamPos;
501         unsigned int skipCount; //JP-EX
502         bool    readDelay;
503
504         TYPE    type;
505         ChannelSource *sourceData;
506
507         SRC_TYPE        srcType;
508
509         MP3Header mp3Head;
510         ThreadInfo      thread;
511         ThreadInfo  *finthread;
512
513         unsigned int lastIdleTime;
514         int             status;
515         static  char *statusMsgs[],*srcTypes[];
516
517         ClientSocket    *sock;
518         ClientSocket    *pushSock;
519
520         unsigned int lastTrackerUpdate;
521         unsigned int lastMetaUpdate;
522
523         double  startTime,syncTime;
524
525         WEvent  syncEvent;
526
527         Channel *next;
528
529         int channel_id;
530         ChanHit chDisp;
531         ChanHit trackerHit;
532         bool bumped;
533         unsigned int lastSkipTime;
534         unsigned int lastStopTime;
535
536         int maxRelays; // \83`\83\83\83\93\83l\83\8b\8cÅ\97L\82Ì\83\8a\83\8c\81[\8dÅ\91å\90\94(\83R\83\93\83X\83g\83\89\83N\83^\82Å\8f\89\8aú\89»)
537 };
538
539 // ----------------------------------
540 class ChanMgr
541 {
542 public:
543         enum {
544                 MAX_IDLE_CHANNELS = 8,          // max. number of channels that can be left idle
545                 MAX_METAINT = 8192                      // must be at least smaller than ChanPacket data len (ie. about half)
546                 
547         };
548
549
550         ChanMgr();
551
552         Channel *deleteChannel(Channel *);
553
554         Channel *createChannel(ChanInfo &,const char *);
555         Channel *findChannelByName(const char *);
556         Channel *findChannelByIndex(int);
557         Channel *findChannelByMount(const char *);
558         Channel *findChannelByID(GnuID &);
559         Channel *findChannelByNameID(ChanInfo &);
560         Channel *findPushChannel(int);
561         Channel *findChannelByChannelID(int id);
562
563         void    broadcastTrackerSettings();
564         void    setUpdateInterval(unsigned int v);
565         void    broadcastRelays(Servent *,int,int);
566
567         int             broadcastPacketUp(ChanPacket &,GnuID &,GnuID &,GnuID &);
568         void    broadcastTrackerUpdate(GnuID &,bool = false);
569
570         bool    writeVariable(Stream &, const String &,int);
571
572         int             findChannels(ChanInfo &,Channel **,int);
573         int             findChannelsByStatus(Channel **,int,Channel::STATUS);
574         
575         int             numIdleChannels();
576         int             numChannels();
577
578         void    closeOldestIdle();
579         void    closeAll();
580         void    quit();
581
582         void    addHit(Host &,GnuID &,bool);
583         ChanHit *addHit(ChanHit &);
584         void    delHit(ChanHit &);
585         void    deadHit(ChanHit &);
586         void    setFirewalled(Host &);
587
588         ChanHitList *findHitList(ChanInfo &);
589         ChanHitList *findHitListByID(GnuID &);
590         ChanHitList     *addHitList(ChanInfo &);
591
592         void            clearHitLists();
593         void            clearDeadHits(bool);
594         int                     numHitLists();
595
596         void            setBroadcastMsg(::String &);
597
598         Channel         *createRelay(ChanInfo &,bool);
599         Channel         *findAndRelay(ChanInfo &);
600         void            startSearch(ChanInfo &);
601
602         void            playChannel(ChanInfo &);
603         void            findAndPlayChannel(ChanInfo &,bool);
604
605         bool            isBroadcasting(GnuID &);
606         bool            isBroadcasting();
607
608         int                     pickHits(ChanHitSearch &);
609
610         bool findParentHit(ChanHit &p);
611
612         Channel         *channel;
613         ChanHitList     *hitlist;
614
615         GnuID   broadcastID;
616
617         ChanInfo        searchInfo;
618
619         int             numFinds;
620         ::String        broadcastMsg;
621         unsigned int            broadcastMsgInterval;
622         unsigned int lastHit,lastQuery;
623         unsigned int maxUptime;
624         bool    searchActive;
625         unsigned int            deadHitAge;
626         int             icyMetaInterval;
627         int             maxRelaysPerChannel;
628         WLock   lock;
629         int             minBroadcastTTL,maxBroadcastTTL;
630         int             pushTimeout,pushTries,maxPushHops;
631         unsigned int            autoQuery;
632         unsigned int    prefetchTime;
633         unsigned int    lastYPConnect;
634         unsigned int    lastYPConnect2;
635         unsigned int    icyIndex;
636
637         unsigned int    hostUpdateInterval;
638         unsigned int bufferTime;
639
640         GnuID   currFindAndPlayChannel;
641
642         WLock channellock;
643         WLock hitlistlock;
644 };
645 // ----------------------------------
646 class PlayList
647 {
648 public:
649
650         enum TYPE
651         {
652                 T_NONE,
653                 T_SCPLS,
654                 T_PLS,
655                 T_ASX,
656                 T_RAM,
657         };
658
659         PlayList(TYPE t, int max)
660         {
661                 maxURLs = max;
662                 numURLs = 0;
663                 type = t;
664                 urls = new ::String[max];
665                 titles = new ::String[max];
666         }
667
668         ~PlayList()
669         {
670                 delete [] urls;
671                 delete [] titles;
672         }
673
674         void    addURL(const char *url, const char *tit)
675         {
676                 if (numURLs < maxURLs)
677                 {
678                         urls[numURLs].set(url);
679                         titles[numURLs].set(tit);
680                         numURLs++;
681                 }
682         }
683         void    addChannels(const char *,Channel **,int);
684         void    addChannel(const char *,ChanInfo &);
685
686         void    writeSCPLS(Stream &);
687         void    writePLS(Stream &);
688         void    writeASX(Stream &);
689         void    writeRAM(Stream &);
690
691         void    readSCPLS(Stream &);
692         void    readPLS(Stream &);
693         void    readASX(Stream &);
694
695         void    read(Stream &s)
696         {
697                 try
698                 {
699                         switch (type)
700                         {
701                                 case T_SCPLS: readSCPLS(s); break;
702                                 case T_PLS: readPLS(s); break;
703                                 case T_ASX: readASX(s); break;
704                         }
705                 }catch(StreamException &) {}    // keep pls regardless of errors (eof isn`t handled properly in sockets)
706         }
707
708         void    write(Stream &s)
709         {
710                 switch (type)
711                 {
712                         case T_SCPLS: writeSCPLS(s); break;
713                         case T_PLS: writePLS(s); break;
714                         case T_ASX: writeASX(s); break;
715                         case T_RAM: writeRAM(s); break;
716                 }
717         }
718
719         TYPE    type;
720         int             numURLs,maxURLs;
721         ::String        *urls,*titles;
722 };
723
724 // ----------------------------------
725
726 extern ChanMgr *chanMgr;
727
728 // for PCRaw start.
729 bool isIndexTxt(ChanInfo *info);
730 bool isIndexTxt(Channel *ch);
731 int numMaxRelaysIndexTxt(Channel *ch);
732 int canStreamIndexTxt(Channel *ch);
733 // for PCRaw end
734
735 #endif