OSDN Git Service

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