OSDN Git Service

d1d00fb350cf35cc0af1b78e98c1f88540476b78
[peercast-im/PeerCastIM.git] / c: / Git / PeerCast.root / PeerCast_1 / 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 // ----------------------------------
212 class ChanHitList
213 {
214 public:
215         ChanHitList();
216         ~ChanHitList();
217
218         int             contactTrackers(bool,int,int,int);
219
220         ChanHit *addHit(ChanHit &);
221         void    delHit(ChanHit &);
222         void    deadHit(ChanHit &);
223         void    clearHits(bool);
224         int             numHits();
225         int             numListeners();
226         int             numRelays();
227         int             numFirewalled();
228         int             numTrackers();
229         int             closestHit();
230         int             furthestHit();
231         unsigned int            newestHit();
232
233         int                     pickHits(ChanHitSearch &);
234         int                     pickSourceHits(ChanHitSearch &);
235
236         bool    isUsed() {return used;}
237         int             clearDeadHits(unsigned int,bool);
238         XML::Node *createXML(bool addHits = true);
239
240         ChanHit *deleteHit(ChanHit *);
241
242         int             getTotalListeners();
243         int             getTotalRelays();
244         int             getTotalFirewalled();
245
246         bool    used;
247         ChanInfo        info;
248         ChanHit *hit;
249         unsigned int lastHitTime;
250         ChanHitList *next;
251
252
253 };
254 // ----------------------------------
255 class ChanHitSearch
256 {
257 public:
258         enum
259         {
260                 MAX_RESULTS = 8
261         };
262
263         ChanHitSearch() { init(); }
264         void init();
265
266         ChanHit best[MAX_RESULTS];
267         Host    matchHost;
268         unsigned int waitDelay;
269         bool    useFirewalled;
270         bool    trackersOnly;
271         bool    useBusyRelays,useBusyControls;
272         GnuID   excludeID;
273         int             numResults;
274         unsigned int seed;
275
276         int getRelayHost(Host host1, Host host2, GnuID exID, ChanHitList *chl);
277 };
278
279 // ----------------------------------
280 class ChanMeta
281 {
282 public:
283         enum {
284                 MAX_DATALEN = 65536
285         };
286
287         void    init()
288         {
289                 len = 0;
290                 cnt = 0;
291                 startPos = 0;
292         }
293
294         void    fromXML(XML &);
295         void    fromMem(void *,int);
296         void    addMem(void *,int);
297
298         unsigned int len,cnt,startPos;
299         char    data[MAX_DATALEN];
300 };
301
302
303
304 // ------------------------------------------
305 class RawStream : public ChannelStream
306 {
307 public:
308         virtual void readHeader(Stream &,Channel *);
309         virtual int readPacket(Stream &,Channel *);
310         virtual void readEnd(Stream &,Channel *);
311
312 };
313
314 // ------------------------------------------
315 class PeercastStream : public ChannelStream
316 {
317 public:
318         virtual void readHeader(Stream &,Channel *);
319         virtual int  readPacket(Stream &,Channel *);
320         virtual void readEnd(Stream &,Channel *);
321 };
322
323 // ------------------------------------------
324 class ChannelSource
325 {
326 public:
327         virtual ~ChannelSource() {}
328         virtual void stream(Channel *) = 0;
329
330         virtual int getSourceRate() {return 0;}
331
332 };
333 // ------------------------------------------
334 class PeercastSource : public ChannelSource
335 {
336 public:
337
338
339         virtual void stream(Channel *);
340
341 };
342
343
344 // ----------------------------------
345 class Channel
346 {
347 public:
348         
349         enum STATUS
350         {
351                 S_NONE,
352                 S_WAIT,
353                 S_CONNECTING,
354                 S_REQUESTING,
355                 S_CLOSING,
356                 S_RECEIVING,
357                 S_BROADCASTING,
358                 S_ABORT,
359                 S_SEARCHING,
360                 S_NOHOSTS,
361                 S_IDLE,
362                 S_ERROR,
363                 S_NOTFOUND
364         };
365
366         enum TYPE
367         {
368                 T_NONE,
369                 T_ALLOCATED,
370                 T_BROADCAST,
371                 T_RELAY
372         };
373
374         enum SRC_TYPE
375         {
376                 SRC_NONE,
377                 SRC_PEERCAST,
378                 SRC_SHOUTCAST,
379                 SRC_ICECAST,
380                 SRC_URL
381         };
382
383
384         Channel();
385         void    reset();
386         void    endThread(bool flg);
387
388         void    startMP3File(char *);
389         void    startGet();
390         void    startICY(ClientSocket *,SRC_TYPE);
391         void    startURL(const char *);
392
393
394         ChannelStream   *createSource();
395
396         void    resetPlayTime();
397
398         bool    notFound()
399         {
400                 return (status == S_NOTFOUND);
401         }
402
403         bool    isPlaying()
404         {
405                 return (status == S_RECEIVING) || (status == S_BROADCASTING);
406         }
407
408         bool    isReceiving()
409         {
410                 return (status == S_RECEIVING);
411         }
412
413         bool    isBroadcasting()
414         {
415                 return (status == S_BROADCASTING);
416         }
417
418         bool    isFull();
419
420         bool    checkBump();
421
422         bool    checkIdle();
423         void    sleepUntil(double);
424
425         bool    isActive()
426         {
427                 return type != T_NONE;
428         }
429
430
431         void    connectFetch();
432         int             handshakeFetch();
433
434         bool    isIdle() {return isActive() && (status==S_IDLE);}
435
436         static THREAD_PROC      stream(ThreadInfo *);
437
438         static THREAD_PROC  waitFinish(ThreadInfo *);
439
440         void    setStatus(STATUS s);
441         const char  *getSrcTypeStr() {return srcTypes[srcType];}
442         const char      *getStatusStr() {return statusMsgs[status];}
443         const char      *getName() {return info.name.cstr();}
444         GnuID   getID() {return info.id;}
445         int             getBitrate() {return info.bitrate; }
446         void    getIDStr(char *s) {info.id.toStr(s);}
447         void    getStreamPath(char *);
448
449         void    broadcastTrackerUpdate(GnuID &,bool = false);
450         bool    sendPacketUp(ChanPacket &,GnuID &,GnuID &,GnuID &);
451
452         bool    writeVariable(Stream &, const String &,int);
453
454         bool    acceptGIV(ClientSocket *);
455
456         void    updateInfo(ChanInfo &);
457
458         int             readStream(Stream &,ChannelStream *);
459         
460         void    checkReadDelay(unsigned int);
461
462         void    processMp3Metadata(char *);
463
464         void    readHeader();
465
466         void    startStream();
467
468         XML::Node *createRelayXML(bool);
469
470         void    newPacket(ChanPacket &);
471
472         int             localListeners();
473         int             localRelays();
474
475         int             totalListeners();
476         int             totalRelays();
477
478         ::String mount;
479         ChanMeta        insertMeta;
480         ChanPacket      headPack;
481
482         ChanPacketBuffer        rawData;
483
484         ChannelStream *sourceStream;
485         unsigned int streamIndex;
486         
487
488         ChanInfo        info;
489         ChanHit         sourceHost;
490
491         GnuID           remoteID;
492
493
494         ::String  sourceURL;
495
496         bool    bump,stayConnected;
497         int             icyMetaInterval;
498         unsigned int streamPos;
499         unsigned int skipCount; //JP-EX
500         bool    readDelay;
501
502         TYPE    type;
503         ChannelSource *sourceData;
504
505         SRC_TYPE        srcType;
506
507         MP3Header mp3Head;
508         ThreadInfo      thread;
509         ThreadInfo  *finthread;
510
511         unsigned int lastIdleTime;
512         int             status;
513         static  char *statusMsgs[],*srcTypes[];
514
515         ClientSocket    *sock;
516         ClientSocket    *pushSock;
517
518         unsigned int lastTrackerUpdate;
519         unsigned int lastMetaUpdate;
520
521         double  startTime,syncTime;
522
523         WEvent  syncEvent;
524
525         Channel *next;
526
527         int channel_id;
528         ChanHit chDisp;
529         ChanHit trackerHit;
530         bool bumped;
531         unsigned int lastSkipTime;
532         unsigned int lastStopTime;
533 };
534
535 // ----------------------------------
536 class ChanMgr
537 {
538 public:
539         enum {
540                 MAX_IDLE_CHANNELS = 8,          // max. number of channels that can be left idle
541                 MAX_METAINT = 8192                      // must be at least smaller than ChanPacket data len (ie. about half)
542                 
543         };
544
545
546         ChanMgr();
547
548         Channel *deleteChannel(Channel *);
549
550         Channel *createChannel(ChanInfo &,const char *);
551         Channel *findChannelByName(const char *);
552         Channel *findChannelByIndex(int);
553         Channel *findChannelByMount(const char *);
554         Channel *findChannelByID(GnuID &);
555         Channel *findChannelByNameID(ChanInfo &);
556         Channel *findPushChannel(int);
557         Channel *findChannelByChannelID(int id);
558
559         void    broadcastTrackerSettings();
560         void    setUpdateInterval(unsigned int v);
561         void    broadcastRelays(Servent *,int,int);
562
563         int             broadcastPacketUp(ChanPacket &,GnuID &,GnuID &,GnuID &);
564         void    broadcastTrackerUpdate(GnuID &,bool = false);
565
566         bool    writeVariable(Stream &, const String &,int);
567
568         int             findChannels(ChanInfo &,Channel **,int);
569         int             findChannelsByStatus(Channel **,int,Channel::STATUS);
570         
571         int             numIdleChannels();
572         int             numChannels();
573
574         void    closeOldestIdle();
575         void    closeAll();
576         void    quit();
577
578         void    addHit(Host &,GnuID &,bool);
579         ChanHit *addHit(ChanHit &);
580         void    delHit(ChanHit &);
581         void    deadHit(ChanHit &);
582         void    setFirewalled(Host &);
583
584         ChanHitList *findHitList(ChanInfo &);
585         ChanHitList *findHitListByID(GnuID &);
586         ChanHitList     *addHitList(ChanInfo &);
587
588         void            clearHitLists();
589         void            clearDeadHits(bool);
590         int                     numHitLists();
591
592         void            setBroadcastMsg(::String &);
593
594         Channel         *createRelay(ChanInfo &,bool);
595         Channel         *findAndRelay(ChanInfo &);
596         void            startSearch(ChanInfo &);
597
598         void            playChannel(ChanInfo &);
599         void            findAndPlayChannel(ChanInfo &,bool);
600
601         bool            isBroadcasting(GnuID &);
602         bool            isBroadcasting();
603
604         int                     pickHits(ChanHitSearch &);
605
606
607
608         Channel         *channel;
609         ChanHitList     *hitlist;
610
611         GnuID   broadcastID;
612
613         ChanInfo        searchInfo;
614
615         int             numFinds;
616         ::String        broadcastMsg;
617         unsigned int            broadcastMsgInterval;
618         unsigned int lastHit,lastQuery;
619         unsigned int maxUptime;
620         bool    searchActive;
621         unsigned int            deadHitAge;
622         int             icyMetaInterval;
623         int             maxRelaysPerChannel;
624         WLock   lock;
625         int             minBroadcastTTL,maxBroadcastTTL;
626         int             pushTimeout,pushTries,maxPushHops;
627         unsigned int            autoQuery;
628         unsigned int    prefetchTime;
629         unsigned int    lastYPConnect;
630         unsigned int    lastYPConnect2;
631         unsigned int    icyIndex;
632
633         unsigned int    hostUpdateInterval;
634         unsigned int bufferTime;
635
636         GnuID   currFindAndPlayChannel;
637
638         WLock channellock;
639         WLock hitlistlock;
640 };
641 // ----------------------------------
642 class PlayList
643 {
644 public:
645
646         enum TYPE
647         {
648                 T_NONE,
649                 T_SCPLS,
650                 T_PLS,
651                 T_ASX,
652                 T_RAM,
653         };
654
655         PlayList(TYPE t, int max)
656         {
657                 maxURLs = max;
658                 numURLs = 0;
659                 type = t;
660                 urls = new ::String[max];
661                 titles = new ::String[max];
662         }
663
664         ~PlayList()
665         {
666                 delete [] urls;
667                 delete [] titles;
668         }
669
670         void    addURL(const char *url, const char *tit)
671         {
672                 if (numURLs < maxURLs)
673                 {
674                         urls[numURLs].set(url);
675                         titles[numURLs].set(tit);
676                         numURLs++;
677                 }
678         }
679         void    addChannels(const char *,Channel **,int);
680         void    addChannel(const char *,ChanInfo &);
681
682         void    writeSCPLS(Stream &);
683         void    writePLS(Stream &);
684         void    writeASX(Stream &);
685         void    writeRAM(Stream &);
686
687         void    readSCPLS(Stream &);
688         void    readPLS(Stream &);
689         void    readASX(Stream &);
690
691         void    read(Stream &s)
692         {
693                 try
694                 {
695                         switch (type)
696                         {
697                                 case T_SCPLS: readSCPLS(s); break;
698                                 case T_PLS: readPLS(s); break;
699                                 case T_ASX: readASX(s); break;
700                         }
701                 }catch(StreamException &) {}    // keep pls regardless of errors (eof isn`t handled properly in sockets)
702         }
703
704         void    write(Stream &s)
705         {
706                 switch (type)
707                 {
708                         case T_SCPLS: writeSCPLS(s); break;
709                         case T_PLS: writePLS(s); break;
710                         case T_ASX: writeASX(s); break;
711                         case T_RAM: writeRAM(s); break;
712                 }
713         }
714
715         TYPE    type;
716         int             numURLs,maxURLs;
717         ::String        *urls,*titles;
718 };
719
720 // ----------------------------------
721
722 extern ChanMgr *chanMgr;
723
724 // for PCRaw start.
725 bool isIndexTxt(ChanInfo *info);
726 bool isIndexTxt(Channel *ch);
727 int numMaxRelaysIndexTxt(Channel *ch);
728 int canStreamIndexTxt(Channel *ch);
729 // for PCRaw end
730
731 #endif