OSDN Git Service

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