OSDN Git Service

38291682f911e6f5047a6c93e0e5bbf8f30fee9d
[peercast-im/PeerCastIM.git] / c: / Git / PeerCast.root / PeerCast / core / common / servmgr.cpp
1 // ------------------------------------------------
2 // File : servmgr.cpp
3 // Date: 4-apr-2002
4 // Author: giles
5 // Desc: 
6 //              Management class for handling multiple servent connections.
7 //
8 // (c) 2002 peercast.org
9 // ------------------------------------------------
10 // This program is free software; you can redistribute it and/or modify
11 // it under the terms of the GNU General Public License as published by
12 // the Free Software Foundation; either version 2 of the License, or
13 // (at your option) any later version.
14
15 // This program is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 // GNU General Public License for more details.
19 // ------------------------------------------------
20
21 #include <stdlib.h>
22 #include "servent.h"
23 #include "servmgr.h"
24 #include "inifile.h"
25 #include "stats.h"
26 #include "peercast.h"
27 #include "pcp.h"
28 #include "atom.h"
29 #include "version2.h"
30 #ifdef _DEBUG
31 #include "chkMemoryLeak.h"
32 #define DEBUG_NEW new(__FILE__, __LINE__)
33 #define new DEBUG_NEW
34 #endif
35
36 ThreadInfo ServMgr::serverThread,ServMgr::idleThread;
37
38 // -----------------------------------
39 ServMgr::ServMgr()
40 {
41         validBCID = NULL;
42
43         authType = AUTH_COOKIE;
44         cookieList.init();
45
46         serventNum = 0;
47
48         startTime = sys->getTime();
49
50         allowServer1 = Servent::ALLOW_ALL;
51         allowServer2 = Servent::ALLOW_BROADCAST;
52
53         clearHostCache(ServHost::T_NONE);
54         password[0]=0;
55
56         allowGnutella = false;
57         useFlowControl = true;
58
59         maxServIn = 50;
60         minGnuIncoming = 10;
61         maxGnuIncoming = 20;
62
63         lastIncoming = 0;
64
65         maxBitrateOut = 540; //JP-Patch 0-> 540
66         maxRelays = MIN_RELAYS;
67         maxDirect = 0;
68         refreshHTML = 1800;
69
70         networkID.clear();
71
72         notifyMask = 0xffff;
73
74         tryoutDelay = 10;
75         numVersions = 0;
76
77         sessionID.generate();
78
79         isDisabled = false;
80         isRoot = false;
81
82         forceIP.clear();
83
84         strcpy(connectHost,"connect1.peercast.org");
85         strcpy(htmlPath,"html/ja");
86
87         rootHost = "yp.peercast.org";
88         rootHost2 = "";
89
90         serverHost.fromStrIP("127.0.0.1",DEFAULT_PORT);
91
92         firewalled = FW_UNKNOWN;                
93         allowDirect = true;
94         autoConnect = true;
95         forceLookup = true;
96         autoServe = true;
97         forceNormal = false;
98
99         maxControl = 3;
100
101         queryTTL = 7;
102
103         totalStreams = 0;
104         firewallTimeout = 30;
105         pauseLog = false;
106         showLog = 0;
107
108         shutdownTimer = 0;
109
110         downloadURL[0] = 0;
111         rootMsg.clear();
112
113
114         restartServer=false;
115
116         setFilterDefaults();
117
118         servents = NULL;
119
120         modulePath[0] = 0; //JP-EX
121         kickPushStartRelays = 1; //JP-EX
122         kickPushInterval = 60; //JP-EX
123         kickPushTime = 0; //JP-EX
124         autoRelayKeep = 2; //JP-EX
125         autoMaxRelaySetting = 0; //JP-EX
126         autoBumpSkipCount = 50; //JP-EX
127         enableGetName = 1; //JP-EX
128         allowConnectPCST = 0; //JP-EX
129         getModulePath = true; //JP-EX
130         clearPLS = false; //JP-EX
131         writeLogFile = false; //JP-EX
132
133         autoPort0Kick = false;
134         allowOnlyVP = false;
135         kickKeepTime = 0;
136         vpDebug = false;
137         saveIniChannel = true;
138         saveGuiPos = false;
139         keepDownstreams = true;
140
141         topmostGui = false;
142         startWithGui = false;
143
144         chanLog="";
145
146         maxRelaysIndexTxt = 1;  // for PCRaw (relay)
147 }
148 // -----------------------------------
149 BCID *ServMgr::findValidBCID(int index)
150 {
151         int cnt = 0;
152         BCID *bcid = validBCID;
153         while (bcid)
154         {
155                 if (cnt == index)
156                         return bcid;
157                 cnt++;
158                 bcid=bcid->next;
159         }
160         return 0;
161 }
162 // -----------------------------------
163 BCID *ServMgr::findValidBCID(GnuID &id)
164 {
165         BCID *bcid = validBCID;
166         while (bcid)
167         {
168                 if (bcid->id.isSame(id))
169                         return bcid;
170                 bcid=bcid->next;
171         }
172         return 0;
173 }
174 // -----------------------------------
175 void ServMgr::removeValidBCID(GnuID &id)
176 {
177         BCID *bcid = validBCID,*prev=0;
178         while (bcid)
179         {
180                 if (bcid->id.isSame(id))
181                 {
182                         if (prev)
183                                 prev->next = bcid->next;
184                         else
185                                 validBCID = bcid->next;
186                         return;
187                 }
188                 prev = bcid;
189                 bcid=bcid->next;
190         }
191 }
192 // -----------------------------------
193 void ServMgr::addValidBCID(BCID *bcid)
194 {
195         removeValidBCID(bcid->id);
196
197         bcid->next = validBCID;
198         validBCID = bcid;
199 }
200
201 // -----------------------------------
202 void    ServMgr::connectBroadcaster()
203 {
204         if (!rootHost.isEmpty())
205         {
206                 if (!numUsed(Servent::T_COUT))
207                 {
208                         Servent *sv = allocServent();
209                         if (sv)
210                         {
211                                 sv->initOutgoing(Servent::T_COUT);
212                                 sys->sleep(3000);
213                         }
214                 }
215         }
216 }
217 // -----------------------------------
218 void    ServMgr::addVersion(unsigned int ver)
219 {
220         for(int i=0; i<numVersions; i++)
221                 if (clientVersions[i] == ver)
222                 {
223                         clientCounts[i]++;
224                         return;
225                 }
226
227         if (numVersions < MAX_VERSIONS)
228         {
229                 clientVersions[numVersions] = ver;
230                 clientCounts[numVersions] = 1;
231                 numVersions++;
232         }
233 }
234
235 // -----------------------------------
236 void ServMgr::setFilterDefaults()
237 {
238         numFilters = 0;
239
240         filters[numFilters].host.fromStrIP("255.255.255.255",0);
241 //      filters[numFilters].flags = ServFilter::F_NETWORK|ServFilter::F_DIRECT;
242         filters[numFilters].flags = ServFilter::F_NETWORK;
243
244         numFilters++;
245
246 }
247
248 // -----------------------------------
249 void    ServMgr::setPassiveSearch(unsigned int t)
250 {
251 //      if ((t > 0) && (t < 60))
252 //              t = 60;
253 //      passiveSearch = t;
254 }
255 // -----------------------------------
256 bool ServMgr::seenHost(Host &h, ServHost::TYPE type,unsigned int time)
257 {
258         time = sys->getTime()-time;
259
260         for(int i=0; i<MAX_HOSTCACHE; i++)
261                 if (hostCache[i].type == type)
262                         if (hostCache[i].host.ip == h.ip)
263                                 if (hostCache[i].time >= time)
264                                         return true;
265         return false;
266 }
267
268 // -----------------------------------
269 void ServMgr::addHost(Host &h, ServHost::TYPE type, unsigned int time)
270 {
271         int i;
272         if (!h.isValid())
273                 return;
274
275         ServHost *sh=NULL;
276
277         for(i=0; i<MAX_HOSTCACHE; i++)
278                 if (hostCache[i].type == type)
279                         if (hostCache[i].host.isSame(h))
280                         {
281                                 sh = &hostCache[i];
282                                 break;
283                         }
284
285         char str[64];
286         h.toStr(str);
287
288         if (!sh)
289                 LOG_DEBUG("New host: %s - %s",str,ServHost::getTypeStr(type));
290         else
291                 LOG_DEBUG("Old host: %s - %s",str,ServHost::getTypeStr(type));
292
293         h.value = 0;    // make sure dead count is zero
294         if (!sh)
295         {
296
297
298                 // find empty slot
299                 for(i=0; i<MAX_HOSTCACHE; i++)
300                         if (hostCache[i].type == ServHost::T_NONE)
301                         {
302                                 sh = &hostCache[i];
303                                 break;
304                         }
305
306                 // otherwise, find oldest host and replace
307                 if (!sh)
308                         for(i=0; i<MAX_HOSTCACHE; i++)
309                                 if (hostCache[i].type != ServHost::T_NONE)
310                                 {
311                                         if (sh)
312                                         {
313                                                 if (hostCache[i].time < sh->time)
314                                                         sh = &hostCache[i];
315                                         }else{
316                                                 sh = &hostCache[i];
317                                         }
318                                 }
319         }
320
321         if (sh)
322                 sh->init(h,type,time);
323 }
324
325 // -----------------------------------
326 void ServMgr::deadHost(Host &h,ServHost::TYPE t)
327 {
328         for(int i=0; i<MAX_HOSTCACHE; i++)
329                 if (hostCache[i].type == t)
330                         if (hostCache[i].host.ip == h.ip)
331                                 if (hostCache[i].host.port == h.port)
332                                         hostCache[i].init();
333 }
334 // -----------------------------------
335 void ServMgr::clearHostCache(ServHost::TYPE type)
336 {
337         for(int i=0; i<MAX_HOSTCACHE; i++)
338                 if ((hostCache[i].type == type) || (type == ServHost::T_NONE))
339                         hostCache[i].init();
340 }
341         
342 // -----------------------------------
343 unsigned int ServMgr::numHosts(ServHost::TYPE type)
344 {
345         unsigned int cnt = 0;
346         for(int i=0; i<MAX_HOSTCACHE; i++)
347                 if ((hostCache[i].type == type) || (type == ServHost::T_NONE))
348                         cnt++;
349         return cnt;
350 }
351 // -----------------------------------
352 int ServMgr::getNewestServents(Host *hl,int max,Host &rh)
353 {
354         int cnt=0;
355         for(int i=0; i<max; i++)
356         {
357                 // find newest host not in list
358                 ServHost *sh=NULL;
359                 for(int j=0; j<MAX_HOSTCACHE; j++)
360                 {
361                         // find newest servent
362                         if (hostCache[j].type == ServHost::T_SERVENT)
363                                 if (!(rh.globalIP() && !hostCache[j].host.globalIP()))
364                                 {
365                                         // and not in list already
366                                         bool found=false;
367                                         for(int k=0; k<cnt; k++)
368                                                 if (hl[k].isSame(hostCache[j].host))
369                                                 {
370                                                         found=true; 
371                                                         break;
372                                                 }
373
374                                         if (!found)
375                                         {
376                                                 if (!sh)
377                                                 {
378                                                         sh = &hostCache[j];
379                                                 }else{
380                                                         if (hostCache[j].time > sh->time)
381                                                                 sh = &hostCache[j];
382                                                 }
383                                         }
384                                 }
385                 }
386
387                 // add to list
388                 if (sh)
389                         hl[cnt++]=sh->host;
390         }
391         
392         return cnt;
393 }
394 // -----------------------------------
395 ServHost ServMgr::getOutgoingServent(GnuID &netid)
396 {
397         ServHost host;
398
399         Host lh(ClientSocket::getIP(NULL),0);
400
401         // find newest host not in list
402         ServHost *sh=NULL;
403         for(int j=0; j<MAX_HOSTCACHE; j++)
404         {
405                 ServHost *hc=&hostCache[j];
406                 // find newest servent not already connected.
407                 if (hc->type == ServHost::T_SERVENT)
408                 {
409                         if (!((lh.globalIP() && !hc->host.globalIP()) || lh.isSame(hc->host)))
410                         {
411 #if 0
412                                 if (!findServent(Servent::T_OUTGOING,hc->host,netid))
413                                 {
414                                         if (!sh)
415                                         {
416                                                 sh = hc;
417                                         }else{
418                                                 if (hc->time > sh->time)
419                                                         sh = hc;
420                                         }
421                                 }
422 #endif
423                         }
424                 }
425         }
426
427         if (sh)
428                 host = *sh;
429
430         return host;
431 }
432 // -----------------------------------
433 Servent *ServMgr::findOldestServent(Servent::TYPE type, bool priv)
434 {
435         Servent *oldest=NULL;
436
437         Servent *s = servents;
438         while (s)
439         {
440                 if (s->type == type)
441                         if (s->thread.active)
442                                 if (s->isOlderThan(oldest))
443                                         if (s->isPrivate() == priv)
444                                                 oldest = s;
445                 s=s->next;
446         }
447         return oldest;
448 }
449 // -----------------------------------
450 Servent *ServMgr::findServent(Servent::TYPE type, Host &host, GnuID &netid)
451 {
452         lock.on();
453         Servent *s = servents;
454         while (s)
455         {
456                 if (s->type == type)
457                 {
458                         Host h = s->getHost();
459                         if (h.isSame(host) && s->networkID.isSame(netid))
460                         {
461                                 lock.off();
462                                 return s;
463                         }
464                 }
465                 s=s->next;
466         }
467         lock.off();
468         return NULL;
469
470 }
471
472 // -----------------------------------
473 Servent *ServMgr::findServent(unsigned int ip, unsigned short port, GnuID &netid)
474 {
475         lock.on();
476         Servent *s = servents;
477         while (s)
478         {
479                 if (s->type != Servent::T_NONE)
480                 {
481                         Host h = s->getHost();
482                         if ((h.ip == ip) && (h.port == port) && (s->networkID.isSame(netid)))
483                         {
484                                 lock.off();
485                                 return s;
486                         }
487                 }
488                 s=s->next;
489         }
490         lock.off();
491         return NULL;
492
493 }
494
495 // -----------------------------------
496 Servent *ServMgr::findServent(Servent::TYPE t)
497 {
498         Servent *s = servents;
499         while (s)
500         {
501                 if (s->type == t)
502                         return s;
503                 s=s->next;
504         }
505         return NULL;
506 }
507 // -----------------------------------
508 Servent *ServMgr::findServentByIndex(int id)
509 {
510         Servent *s = servents;
511         int cnt=0;
512         while (s)
513         {
514                 if (cnt == id)
515                         return s;
516                         cnt++;
517                 s=s->next;
518         }
519         return NULL;
520 }
521
522 // -----------------------------------
523 Servent *ServMgr::findServentByServentID(int id)
524 {
525         Servent *s = servents;
526         while (s)
527         {
528                 if (id == s->servent_id){
529                         return s;
530                 }
531                 s=s->next;
532         }
533         return NULL;
534 }
535
536 // -----------------------------------
537 Servent *ServMgr::allocServent()
538 {
539         lock.on();
540
541         Servent *s = servents;
542         while (s)
543         {
544                 if (s->status == Servent::S_FREE)
545                         break;
546                 s=s->next;
547         }
548
549         if (!s)
550         {
551                 s = new Servent(++serventNum);
552                 s->next = servents;
553                 servents = s;
554
555                 LOG_DEBUG("allocated servent %d",serventNum);
556         }else
557                 LOG_DEBUG("reused servent %d",s->serventIndex);
558
559
560         s->reset();
561
562         lock.off();
563
564         return s;
565 }
566 // --------------------------------------------------
567 void    ServMgr::closeConnections(Servent::TYPE type)
568 {
569         Servent *sv = servents;
570         while (sv)
571         {
572                 if (sv->isConnected())
573                         if (sv->type == type)
574                                 sv->thread.active = false;
575                 sv=sv->next;
576         }
577 }
578
579 // -----------------------------------
580 unsigned int ServMgr::numConnected(int type,bool priv,unsigned int uptime)
581 {
582         unsigned int cnt=0;
583
584         unsigned int ctime=sys->getTime();
585         Servent *s = servents;
586         while (s)
587         {
588                 if (s->thread.active)
589                         if (s->isConnected())
590                                 if (s->type == type)
591                                         if (s->isPrivate()==priv)
592                                                 if ((ctime-s->lastConnect) >= uptime)
593                                                         cnt++;
594
595                 s=s->next;
596         }
597         return cnt;
598 }
599 // -----------------------------------
600 unsigned int ServMgr::numConnected()
601 {
602         unsigned int cnt=0;
603
604         Servent *s = servents;
605         while (s)
606         {
607                 if (s->thread.active)
608                         if (s->isConnected())
609                                 cnt++;
610
611                 s=s->next;
612         }
613         return cnt;
614 }
615 // -----------------------------------
616 unsigned int ServMgr::numServents()
617 {
618         unsigned int cnt=0;
619
620         Servent *s = servents;
621         while (s)
622         {
623                 cnt++;
624                 s=s->next;
625         }
626         return cnt;
627 }
628
629 // -----------------------------------
630 unsigned int ServMgr::numUsed(int type)
631 {
632         unsigned int cnt=0;
633
634         Servent *s = servents;
635         while (s)
636         {
637                 if (s->type == type)
638                         cnt++;
639                 s=s->next;
640         }
641         return cnt;
642 }
643 // -----------------------------------
644 unsigned int ServMgr::numActiveOnPort(int port)
645 {
646         unsigned int cnt=0;
647
648         Servent *s = servents;
649         while (s)
650         {
651                 if (s->thread.active && s->sock && (s->servPort == port))
652                         cnt++;
653                 s=s->next;
654         }
655         return cnt;
656 }
657 // -----------------------------------
658 unsigned int ServMgr::numActive(Servent::TYPE tp)
659 {
660         unsigned int cnt=0;
661
662         Servent *s = servents;
663         while (s)
664         {
665                 if (s->thread.active && s->sock && (s->type == tp))
666                         cnt++;
667                 s=s->next;
668         }
669         return cnt;
670 }
671
672 // -----------------------------------
673 unsigned int ServMgr::totalOutput(bool all)
674 {
675         unsigned int tot = 0;
676         Servent *s = servents;
677         while (s)
678         {
679                 if (s->isConnected())
680                         if (all || !s->isPrivate())
681                                 if (s->sock)
682                                         tot += s->sock->bytesOutPerSec;
683                 s=s->next;
684         }
685
686         return tot;
687 }
688
689 // -----------------------------------
690 unsigned int ServMgr::totalInput(bool all)
691 {
692         unsigned int tot = 0;
693         Servent *s = servents;
694         while (s)
695         {
696                 if (s->isConnected())
697                         if (all || !s->isPrivate())
698                                 if (s->sock)
699                                         tot += s->sock->bytesInPerSec;
700                 s=s->next;
701         }
702
703         return tot;
704 }
705
706 // -----------------------------------
707 unsigned int ServMgr::numOutgoing()
708 {
709         int cnt=0;
710
711         Servent *s = servents;
712         while (s)
713         {
714 //              if ((s->type == Servent::T_INCOMING) ||
715 //                  (s->type == Servent::T_OUTGOING)) 
716 //                      cnt++;
717                 s=s->next;
718         }
719         return cnt;
720 }
721
722 // -----------------------------------
723 bool ServMgr::seenPacket(GnuPacket &p)
724 {
725         Servent *s = servents;
726         while (s)
727         {
728                 if (s->isConnected())
729                         if (s->seenIDs.contains(p.id))
730                                 return true;
731                 s=s->next;
732         }
733         return false;
734 }
735
736 // -----------------------------------
737 void ServMgr::quit()
738 {
739         LOG_DEBUG("ServMgr is quitting..");
740
741         serverThread.shutdown();
742
743         idleThread.shutdown();
744
745         Servent *s = servents;
746         while (s)
747         {
748                 try
749                 {
750                         if (s->thread.active)
751                         {
752                                 s->thread.shutdown();
753                         }
754
755                 }catch(StreamException &)
756                 {
757                 }
758                 s=s->next;
759         }
760 }
761
762 // -----------------------------------
763 int ServMgr::broadcast(GnuPacket &pack,Servent *src)
764 {
765         int cnt=0;
766         if (pack.ttl)
767         {
768                 Servent *s = servents;
769                 while (s)
770                 {
771
772                         if (s != src)
773                                 if (s->isConnected())
774                                         if (s->type == Servent::T_PGNU)
775                                                 if (!s->seenIDs.contains(pack.id))
776                                                 {
777
778                                                         if (src)
779                                                                 if (!src->networkID.isSame(s->networkID))
780                                                                         continue;
781
782                                                         if (s->outputPacket(pack,false))
783                                                                 cnt++;
784                                                 }
785                         s=s->next;
786                 }
787         }
788
789         LOG_NETWORK("broadcast: %s (%d) to %d servents",GNU_FUNC_STR(pack.func),pack.ttl,cnt);
790
791         return cnt;
792 }
793 // -----------------------------------
794 int ServMgr::route(GnuPacket &pack, GnuID &routeID, Servent *src)
795 {
796         int cnt=0;
797         if (pack.ttl)
798         {
799                 Servent *s = servents;
800                 while (s)
801                 {
802                         if (s != src)
803                                 if (s->isConnected())
804                                         if (s->type == Servent::T_PGNU)
805                                                 if (!s->seenIDs.contains(pack.id))
806                                                         if (s->seenIDs.contains(routeID))
807                                                         {
808                                                                 if (src)
809                                                                         if (!src->networkID.isSame(s->networkID))
810                                                                                 continue;
811
812                                                                 if (s->outputPacket(pack,true))
813                                                                         cnt++;
814                                                         }
815                         s=s->next;
816                 }
817
818         }
819
820         LOG_NETWORK("route: %s (%d) to %d servents",GNU_FUNC_STR(pack.func),pack.ttl,cnt);
821         return cnt;
822 }
823 // -----------------------------------
824 bool ServMgr::checkForceIP()
825 {
826         if (!forceIP.isEmpty())
827         {
828                 unsigned int newIP = ClientSocket::getIP(forceIP.cstr());
829                 if (serverHost.ip != newIP)
830                 {
831                         serverHost.ip = newIP;
832                         char ipstr[64];
833                         serverHost.IPtoStr(ipstr);
834                         LOG_DEBUG("Server IP changed to %s",ipstr);
835                         return true;
836                 }
837         }
838         return false;
839 }
840
841 // -----------------------------------
842 void ServMgr::checkFirewall()
843 {
844         if ((getFirewall() == FW_UNKNOWN) && !servMgr->rootHost.isEmpty())
845         {
846
847                 LOG_DEBUG("Checking firewall..");
848                 Host host;
849                 host.fromStrName(servMgr->rootHost.cstr(),DEFAULT_PORT);
850
851                 ClientSocket *sock = sys->createSocket();
852                 if (!sock)
853                         throw StreamException("Unable to create socket");
854                 sock->setReadTimeout(30000);
855                 sock->open(host);
856                 sock->connect();
857
858                 AtomStream atom(*sock);
859
860                 atom.writeInt(PCP_CONNECT,1);
861
862                 GnuID remoteID;
863                 String agent;
864                 Servent::handshakeOutgoingPCP(atom,sock->host,remoteID,agent,true);
865
866                 atom.writeInt(PCP_QUIT,PCP_ERROR_QUIT);
867
868                 sock->close();
869                 delete sock;
870         }
871 }
872
873 // -----------------------------------
874 void ServMgr::setFirewall(FW_STATE state)
875 {
876         if (firewalled != state)
877         {
878                 char *str;
879                 switch (state)
880                 {
881                         case FW_ON:
882                                 str = "ON";
883                                 break;
884                         case FW_OFF:
885                                 str = "OFF";
886                                 break;
887                         case FW_UNKNOWN:
888                         default:
889                                 str = "UNKNOWN";
890                                 break;
891                 }
892
893                 LOG_DEBUG("Firewall is set to %s",str);
894                 firewalled = state;
895         }
896 }
897 // -----------------------------------
898 bool ServMgr::isFiltered(int fl, Host &h)
899 {
900         for(int i=0; i<numFilters; i++)
901                 if (filters[i].flags & fl)
902                         if (h.isMemberOf(filters[i].host))
903                                 return true;
904
905         return false;
906 }
907
908 #if 0
909 // -----------------------------------
910 bool ServMgr::canServeHost(Host &h)
911 {
912         if (server)
913         {
914                 Host sh = server->getHost();
915
916                 if (sh.globalIP() || (sh.localIP() && h.localIP()))
917                         return true;            
918         }
919         return false;
920 }
921 #endif
922
923 // --------------------------------------------------
924 void writeServerSettings(IniFile &iniFile, unsigned int a)
925 {
926         iniFile.writeBoolValue("allowHTML",a & Servent::ALLOW_HTML);
927         iniFile.writeBoolValue("allowBroadcast",a & Servent::ALLOW_BROADCAST);
928         iniFile.writeBoolValue("allowNetwork",a & Servent::ALLOW_NETWORK);
929         iniFile.writeBoolValue("allowDirect",a & Servent::ALLOW_DIRECT);
930 }
931 // --------------------------------------------------
932 void writeFilterSettings(IniFile &iniFile, ServFilter &f)
933 {
934         char ipstr[64];
935         f.host.IPtoStr(ipstr);
936         iniFile.writeStrValue("ip",ipstr);
937         iniFile.writeBoolValue("private",f.flags & ServFilter::F_PRIVATE);
938         iniFile.writeBoolValue("ban",f.flags & ServFilter::F_BAN);
939         iniFile.writeBoolValue("network",f.flags & ServFilter::F_NETWORK);
940         iniFile.writeBoolValue("direct",f.flags & ServFilter::F_DIRECT);
941 }
942
943 // --------------------------------------------------
944 static void  writeServHost(IniFile &iniFile, ServHost &sh)
945 {
946         iniFile.writeSection("Host");
947
948         char ipStr[64];
949         sh.host.toStr(ipStr);
950         iniFile.writeStrValue("type",ServHost::getTypeStr(sh.type));
951         iniFile.writeStrValue("address",ipStr);
952         iniFile.writeIntValue("time",sh.time);
953
954         iniFile.writeLine("[End]");
955 }
956
957 #ifdef WIN32
958 extern bool guiFlg;
959 extern WINDOWPLACEMENT winPlace;
960 extern HWND guiWnd;
961 #endif
962
963 // --------------------------------------------------
964 void ServMgr::saveSettings(const char *fn)
965 {
966         IniFile iniFile;
967         if (!iniFile.openWriteReplace(fn))
968         {
969                 LOG_ERROR("Unable to open ini file");
970         }else{
971                 LOG_DEBUG("Saving settings to:  %s",fn);
972
973                 char idStr[64];
974
975                 iniFile.writeSection("Server");
976                 iniFile.writeIntValue("serverPort",servMgr->serverHost.port);
977                 iniFile.writeBoolValue("autoServe",servMgr->autoServe);
978                 iniFile.writeStrValue("forceIP",servMgr->forceIP);
979                 iniFile.writeBoolValue("isRoot",servMgr->isRoot);
980                 iniFile.writeIntValue("maxBitrateOut",servMgr->maxBitrateOut);
981                 iniFile.writeIntValue("maxRelays",servMgr->maxRelays);
982                 iniFile.writeIntValue("maxDirect",servMgr->maxDirect);
983                 iniFile.writeIntValue("maxRelaysPerChannel",chanMgr->maxRelaysPerChannel);
984                 iniFile.writeIntValue("firewallTimeout",firewallTimeout);
985                 iniFile.writeBoolValue("forceNormal",forceNormal);
986                 iniFile.writeStrValue("rootMsg",rootMsg.cstr());
987                 iniFile.writeStrValue("authType",servMgr->authType==ServMgr::AUTH_COOKIE?"cookie":"http-basic");
988                 iniFile.writeStrValue("cookiesExpire",servMgr->cookieList.neverExpire==true?"never":"session");
989                 iniFile.writeStrValue("htmlPath",servMgr->htmlPath);
990                 iniFile.writeIntValue("minPGNUIncoming",servMgr->minGnuIncoming);
991                 iniFile.writeIntValue("maxPGNUIncoming",servMgr->maxGnuIncoming);
992                 iniFile.writeIntValue("maxServIn",servMgr->maxServIn);
993                 iniFile.writeStrValue("chanLog",servMgr->chanLog.cstr());
994
995                 networkID.toStr(idStr);
996                 iniFile.writeStrValue("networkID",idStr);
997
998
999                 iniFile.writeSection("Broadcast");
1000                 iniFile.writeIntValue("broadcastMsgInterval",chanMgr->broadcastMsgInterval);
1001                 iniFile.writeStrValue("broadcastMsg",chanMgr->broadcastMsg.cstr());
1002                 iniFile.writeIntValue("icyMetaInterval",chanMgr->icyMetaInterval);
1003                 chanMgr->broadcastID.toStr(idStr);
1004                 iniFile.writeStrValue("broadcastID",idStr);             
1005                 iniFile.writeIntValue("hostUpdateInterval",chanMgr->hostUpdateInterval);
1006                 iniFile.writeIntValue("maxControlConnections",servMgr->maxControl);
1007                 iniFile.writeStrValue("rootHost",servMgr->rootHost.cstr());
1008
1009                 iniFile.writeSection("Client");
1010                 iniFile.writeIntValue("refreshHTML",refreshHTML);
1011                 iniFile.writeIntValue("relayBroadcast",servMgr->relayBroadcast);
1012                 iniFile.writeIntValue("minBroadcastTTL",chanMgr->minBroadcastTTL);
1013                 iniFile.writeIntValue("maxBroadcastTTL",chanMgr->maxBroadcastTTL);
1014                 iniFile.writeIntValue("pushTries",chanMgr->pushTries);
1015                 iniFile.writeIntValue("pushTimeout",chanMgr->pushTimeout);
1016                 iniFile.writeIntValue("maxPushHops",chanMgr->maxPushHops);
1017                 iniFile.writeIntValue("autoQuery",chanMgr->autoQuery);
1018                 iniFile.writeIntValue("queryTTL",servMgr->queryTTL);
1019
1020
1021                 iniFile.writeSection("Privacy");
1022                 iniFile.writeStrValue("password",servMgr->password);
1023                 iniFile.writeIntValue("maxUptime",chanMgr->maxUptime);
1024
1025                 //JP-EX
1026                 iniFile.writeSection("Extend");
1027                 iniFile.writeIntValue("autoRelayKeep",servMgr->autoRelayKeep);
1028                 iniFile.writeIntValue("autoMaxRelaySetting",servMgr->autoMaxRelaySetting);
1029                 iniFile.writeIntValue("autoBumpSkipCount",servMgr->autoBumpSkipCount);
1030                 iniFile.writeIntValue("kickPushStartRelays",servMgr->kickPushStartRelays);
1031                 iniFile.writeIntValue("kickPushInterval",servMgr->kickPushInterval);
1032                 iniFile.writeIntValue("allowConnectPCST",servMgr->allowConnectPCST);
1033                 iniFile.writeIntValue("enableGetName",servMgr->enableGetName);
1034
1035                 iniFile.writeIntValue("maxRelaysIndexTxt", servMgr->maxRelaysIndexTxt); // for PCRaw (relay)
1036
1037                 //JP-EX
1038                 iniFile.writeSection("Windows");
1039                 iniFile.writeBoolValue("getModulePath",servMgr->getModulePath);
1040                 iniFile.writeBoolValue("clearPLS",servMgr->clearPLS);
1041                 iniFile.writeBoolValue("writeLogFile",servMgr->writeLogFile);
1042
1043                 //VP-EX
1044                 iniFile.writeStrValue("rootHost2",servMgr->rootHost2.cstr());
1045                 iniFile.writeBoolValue("autoPort0Kick",servMgr->autoPort0Kick);
1046                 iniFile.writeBoolValue("allowOnlyVP",servMgr->allowOnlyVP);
1047                 iniFile.writeIntValue("kickKeepTime",servMgr->kickKeepTime);
1048                 iniFile.writeBoolValue("vpDebug", servMgr->vpDebug);
1049                 iniFile.writeBoolValue("saveIniChannel", servMgr->saveIniChannel);
1050 #ifdef WIN32
1051                 iniFile.writeBoolValue("saveGuiPos", servMgr->saveGuiPos);
1052                 if (guiFlg){
1053                         GetWindowPlacement(guiWnd, &winPlace);
1054                         iniFile.writeIntValue("guiTop", winPlace.rcNormalPosition.top);
1055                         iniFile.writeIntValue("guiBottom", winPlace.rcNormalPosition.bottom);
1056                         iniFile.writeIntValue("guiLeft", winPlace.rcNormalPosition.left);
1057                         iniFile.writeIntValue("guiRight", winPlace.rcNormalPosition.right);
1058                 }
1059
1060                 iniFile.writeBoolValue("topmostGui", servMgr->topmostGui);
1061                 iniFile.writeBoolValue("startWithGui", servMgr->startWithGui);
1062 #endif
1063                 int i;
1064
1065                 for(i=0; i<servMgr->numFilters; i++)
1066                 {
1067                         iniFile.writeSection("Filter");
1068                                 writeFilterSettings(iniFile,servMgr->filters[i]);
1069                         iniFile.writeLine("[End]");
1070                 }
1071
1072                 iniFile.writeSection("Notify");
1073                         iniFile.writeBoolValue("PeerCast",notifyMask&NT_PEERCAST);
1074                         iniFile.writeBoolValue("Broadcasters",notifyMask&NT_BROADCASTERS);
1075                         iniFile.writeBoolValue("TrackInfo",notifyMask&NT_TRACKINFO);
1076                 iniFile.writeLine("[End]");
1077
1078
1079                 iniFile.writeSection("Server1");
1080                         writeServerSettings(iniFile,allowServer1);
1081                 iniFile.writeLine("[End]");
1082
1083                 iniFile.writeSection("Server2");
1084                         writeServerSettings(iniFile,allowServer2);
1085                 iniFile.writeLine("[End]");
1086
1087
1088
1089                 iniFile.writeSection("Debug");
1090                 iniFile.writeBoolValue("logDebug",(showLog&(1<<LogBuffer::T_DEBUG))!=0);
1091                 iniFile.writeBoolValue("logErrors",(showLog&(1<<LogBuffer::T_ERROR))!=0);
1092                 iniFile.writeBoolValue("logNetwork",(showLog&(1<<LogBuffer::T_NETWORK))!=0);
1093                 iniFile.writeBoolValue("logChannel",(showLog&(1<<LogBuffer::T_CHANNEL))!=0);
1094                 iniFile.writeBoolValue("pauseLog",pauseLog);
1095                 iniFile.writeIntValue("idleSleepTime",sys->idleSleepTime);
1096
1097
1098                 if (servMgr->validBCID)
1099                 {
1100                         BCID *bcid = servMgr->validBCID;
1101                         while (bcid)
1102                         {
1103                                 iniFile.writeSection("ValidBCID");
1104                                 char idstr[128];
1105                                 bcid->id.toStr(idstr);
1106                                 iniFile.writeStrValue("id",idstr);
1107                                 iniFile.writeStrValue("name",bcid->name.cstr());
1108                                 iniFile.writeStrValue("email",bcid->email.cstr());
1109                                 iniFile.writeStrValue("url",bcid->url.cstr());
1110                                 iniFile.writeBoolValue("valid",bcid->valid);
1111                                 iniFile.writeLine("[End]");
1112                                 
1113                                 bcid=bcid->next;
1114                         }
1115                 }
1116
1117                 if (servMgr->saveIniChannel){
1118                         Channel *c = chanMgr->channel;
1119                         while (c)
1120                         {
1121                                 char idstr[64];
1122                                 if (c->isActive() && c->stayConnected)
1123                                 {
1124                                         c->getIDStr(idstr);
1125
1126                                         iniFile.writeSection("RelayChannel");
1127                                         iniFile.writeStrValue("name",c->getName());
1128                                         iniFile.writeStrValue("genre",c->info.genre.cstr());
1129                                         if (!c->sourceURL.isEmpty())
1130                                                 iniFile.writeStrValue("sourceURL",c->sourceURL.cstr());
1131                                         iniFile.writeStrValue("sourceProtocol",ChanInfo::getProtocolStr(c->info.srcProtocol));
1132                                         iniFile.writeStrValue("contentType",ChanInfo::getTypeStr(c->info.contentType));
1133                                         iniFile.writeIntValue("bitrate",c->info.bitrate);
1134                                         iniFile.writeStrValue("contactURL",c->info.url.cstr());
1135                                         iniFile.writeStrValue("id",idstr);
1136                                         iniFile.writeBoolValue("stayConnected",c->stayConnected);
1137
1138                                         ChanHitList *chl = chanMgr->findHitListByID(c->info.id);
1139                                         if (chl)
1140                                         {
1141
1142                                                 ChanHitSearch chs;
1143                                                 chs.trackersOnly = true;
1144                                                 if (chl->pickHits(chs))
1145                                                 {
1146                                                         char ipStr[64];
1147                                                         chs.best[0].host.toStr(ipStr);
1148                                                         iniFile.writeStrValue("tracker",ipStr);
1149                                                 }
1150                                         }
1151                                         iniFile.writeLine("[End]");
1152                                 }
1153                                 c=c->next;
1154                         }
1155                 }
1156                 
1157
1158                 
1159 #if 0
1160                 Servent *s = servents;
1161                 while (s)
1162                 {
1163                         if (s->type == Servent::T_OUTGOING)
1164                                 if (s->isConnected())
1165                                 {
1166                                         ServHost sh;
1167                                         Host h = s->getHost();
1168                                         sh.init(h,ServHost::T_SERVENT,0,s->networkID);
1169                                         writeServHost(iniFile,sh);
1170                                 }
1171                         s=s->next;
1172                 }
1173 #endif
1174
1175                 for(i=0; i<ServMgr::MAX_HOSTCACHE; i++)
1176                 {
1177                         ServHost *sh = &servMgr->hostCache[i];
1178                         if (sh->type != ServHost::T_NONE)
1179                                 writeServHost(iniFile,*sh);
1180                 }
1181
1182                 iniFile.close();
1183         }
1184 }
1185 // --------------------------------------------------
1186 unsigned int readServerSettings(IniFile &iniFile, unsigned int a)
1187 {
1188         while (iniFile.readNext())
1189         {
1190                 if (iniFile.isName("[End]"))
1191                         break;
1192                 else if (iniFile.isName("allowHTML"))
1193                         a = iniFile.getBoolValue()?a|Servent::ALLOW_HTML:a&~Servent::ALLOW_HTML;
1194                 else if (iniFile.isName("allowDirect"))
1195                         a = iniFile.getBoolValue()?a|Servent::ALLOW_DIRECT:a&~Servent::ALLOW_DIRECT;
1196                 else if (iniFile.isName("allowNetwork"))
1197                         a = iniFile.getBoolValue()?a|Servent::ALLOW_NETWORK:a&~Servent::ALLOW_NETWORK;
1198                 else if (iniFile.isName("allowBroadcast"))
1199                         a = iniFile.getBoolValue()?a|Servent::ALLOW_BROADCAST:a&~Servent::ALLOW_BROADCAST;
1200         }
1201         return a;
1202 }
1203 // --------------------------------------------------
1204 void readFilterSettings(IniFile &iniFile, ServFilter &sv)
1205 {
1206         sv.host.init();
1207
1208         while (iniFile.readNext())
1209         {
1210                 if (iniFile.isName("[End]"))
1211                         break;
1212                 else if (iniFile.isName("ip"))
1213                         sv.host.fromStrIP(iniFile.getStrValue(),0);
1214                 else if (iniFile.isName("private"))
1215                         sv.flags = (sv.flags & ~ServFilter::F_PRIVATE) | (iniFile.getBoolValue()?ServFilter::F_PRIVATE:0);
1216                 else if (iniFile.isName("ban"))
1217                         sv.flags = (sv.flags & ~ServFilter::F_BAN) | (iniFile.getBoolValue()?ServFilter::F_BAN:0);
1218                 else if (iniFile.isName("allow") || iniFile.isName("network"))
1219                         sv.flags = (sv.flags & ~ServFilter::F_NETWORK) | (iniFile.getBoolValue()?ServFilter::F_NETWORK:0);
1220                 else if (iniFile.isName("direct"))
1221                         sv.flags = (sv.flags & ~ServFilter::F_DIRECT) | (iniFile.getBoolValue()?ServFilter::F_DIRECT:0);
1222         }
1223
1224 }
1225 // --------------------------------------------------
1226 void ServMgr::loadSettings(const char *fn)
1227 {
1228         IniFile iniFile;
1229
1230         if (!iniFile.openReadOnly(fn))
1231                 saveSettings(fn);
1232
1233
1234         servMgr->numFilters = 0;
1235         showLog = 0;
1236
1237         if (iniFile.openReadOnly(fn))
1238         {
1239                 while (iniFile.readNext())
1240                 {
1241                         // server settings
1242                         if (iniFile.isName("serverPort"))
1243                                 servMgr->serverHost.port = iniFile.getIntValue();
1244                         else if (iniFile.isName("autoServe"))
1245                                 servMgr->autoServe = iniFile.getBoolValue();
1246                         else if (iniFile.isName("autoConnect"))
1247                                 servMgr->autoConnect = iniFile.getBoolValue();
1248                         else if (iniFile.isName("icyPassword"))         // depreciated
1249                                 strcpy(servMgr->password,iniFile.getStrValue());
1250                         else if (iniFile.isName("forceIP"))
1251                                 servMgr->forceIP = iniFile.getStrValue();
1252                         else if (iniFile.isName("isRoot"))
1253                                 servMgr->isRoot = iniFile.getBoolValue();
1254                         else if (iniFile.isName("broadcastID"))
1255                         {
1256                                 chanMgr->broadcastID.fromStr(iniFile.getStrValue());
1257                                 chanMgr->broadcastID.id[0] = PCP_BROADCAST_FLAGS;                       // hacky, but we need to fix old clients
1258
1259                         }else if (iniFile.isName("htmlPath"))
1260                                 strcpy(servMgr->htmlPath,iniFile.getStrValue());
1261                         else if (iniFile.isName("maxPGNUIncoming"))
1262                                 servMgr->maxGnuIncoming = iniFile.getIntValue();
1263                         else if (iniFile.isName("minPGNUIncoming"))
1264                                 servMgr->minGnuIncoming = iniFile.getIntValue();
1265
1266                         else if (iniFile.isName("maxControlConnections"))
1267                         {
1268                                 servMgr->maxControl = iniFile.getIntValue();
1269
1270                         }
1271                         else if (iniFile.isName("maxBitrateOut"))
1272                                 servMgr->maxBitrateOut = iniFile.getIntValue();
1273
1274                         else if (iniFile.isName("maxStreamsOut"))               // depreciated
1275                                 servMgr->setMaxRelays(iniFile.getIntValue());
1276                         else if (iniFile.isName("maxRelays"))           
1277                                 servMgr->setMaxRelays(iniFile.getIntValue());
1278                         else if (iniFile.isName("maxDirect"))           
1279                                 servMgr->maxDirect = iniFile.getIntValue();
1280
1281                         else if (iniFile.isName("maxStreamsPerChannel"))                // depreciated
1282                                 chanMgr->maxRelaysPerChannel = iniFile.getIntValue();
1283                         else if (iniFile.isName("maxRelaysPerChannel"))
1284                                 chanMgr->maxRelaysPerChannel = iniFile.getIntValue();
1285
1286                         else if (iniFile.isName("firewallTimeout"))
1287                                 firewallTimeout = iniFile.getIntValue();
1288                         else if (iniFile.isName("forceNormal"))
1289                                 forceNormal = iniFile.getBoolValue();
1290                         else if (iniFile.isName("broadcastMsgInterval"))
1291                                 chanMgr->broadcastMsgInterval = iniFile.getIntValue();
1292                         else if (iniFile.isName("broadcastMsg"))
1293                                 chanMgr->broadcastMsg.set(iniFile.getStrValue(),String::T_ASCII);
1294                         else if (iniFile.isName("hostUpdateInterval"))
1295                                 chanMgr->hostUpdateInterval = iniFile.getIntValue();
1296                         else if (iniFile.isName("icyMetaInterval"))
1297                                 chanMgr->icyMetaInterval = iniFile.getIntValue();
1298                         else if (iniFile.isName("maxServIn"))
1299                                 servMgr->maxServIn = iniFile.getIntValue();
1300                         else if (iniFile.isName("chanLog"))
1301                                 servMgr->chanLog.set(iniFile.getStrValue(),String::T_ASCII);
1302
1303                         else if (iniFile.isName("rootMsg"))
1304                                 rootMsg.set(iniFile.getStrValue());
1305                         else if (iniFile.isName("networkID"))
1306                                 networkID.fromStr(iniFile.getStrValue());
1307                         else if (iniFile.isName("authType"))
1308                         {
1309                                 char *t = iniFile.getStrValue();
1310                                 if (stricmp(t,"cookie")==0)
1311                                         servMgr->authType = ServMgr::AUTH_COOKIE;
1312                                 else if (stricmp(t,"http-basic")==0)
1313                                         servMgr->authType = ServMgr::AUTH_HTTPBASIC;
1314                         }else if (iniFile.isName("cookiesExpire"))
1315                         {
1316                                 char *t = iniFile.getStrValue();
1317                                 if (stricmp(t,"never")==0)
1318                                         servMgr->cookieList.neverExpire = true;
1319                                 else if (stricmp(t,"session")==0)
1320                                         servMgr->cookieList.neverExpire = false;
1321
1322
1323                         }
1324
1325                         // privacy settings
1326                         else if (iniFile.isName("password"))
1327                                 strcpy(servMgr->password,iniFile.getStrValue());
1328                         else if (iniFile.isName("maxUptime"))
1329                                 chanMgr->maxUptime = iniFile.getIntValue();
1330
1331                         // client settings
1332
1333                         else if (iniFile.isName("rootHost"))
1334                         {
1335                                 if (!PCP_FORCE_YP)
1336                                         servMgr->rootHost = iniFile.getStrValue();
1337
1338                         }else if (iniFile.isName("deadHitAge"))
1339                                 chanMgr->deadHitAge = iniFile.getIntValue();
1340                         else if (iniFile.isName("tryoutDelay"))
1341                                 servMgr->tryoutDelay = iniFile.getIntValue();
1342                         else if (iniFile.isName("refreshHTML"))
1343                                 refreshHTML = iniFile.getIntValue();
1344                         else if (iniFile.isName("relayBroadcast"))
1345                         {
1346                                 servMgr->relayBroadcast = iniFile.getIntValue();
1347                                 if (servMgr->relayBroadcast < 30)
1348                                         servMgr->relayBroadcast = 30;
1349                         }
1350                         else if (iniFile.isName("minBroadcastTTL"))
1351                                 chanMgr->minBroadcastTTL = iniFile.getIntValue();
1352                         else if (iniFile.isName("maxBroadcastTTL"))
1353                                 chanMgr->maxBroadcastTTL = iniFile.getIntValue();
1354                         else if (iniFile.isName("pushTimeout"))
1355                                 chanMgr->pushTimeout = iniFile.getIntValue();
1356                         else if (iniFile.isName("pushTries"))
1357                                 chanMgr->pushTries = iniFile.getIntValue();
1358                         else if (iniFile.isName("maxPushHops"))
1359                                 chanMgr->maxPushHops = iniFile.getIntValue();
1360                         else if (iniFile.isName("autoQuery"))
1361                         {
1362                                 chanMgr->autoQuery = iniFile.getIntValue();
1363                                 if ((chanMgr->autoQuery < 300) && (chanMgr->autoQuery > 0))
1364                                         chanMgr->autoQuery = 300;
1365                         }
1366                         else if (iniFile.isName("queryTTL"))
1367                         {
1368                                 servMgr->queryTTL = iniFile.getIntValue();
1369                         }
1370
1371                         //JP-Extend
1372                         else if (iniFile.isName("autoRelayKeep"))
1373                                 servMgr->autoRelayKeep = iniFile.getIntValue();
1374                         else if (iniFile.isName("autoMaxRelaySetting"))
1375                                 servMgr->autoMaxRelaySetting = iniFile.getIntValue();
1376                         else if (iniFile.isName("autoBumpSkipCount"))
1377                                 servMgr->autoBumpSkipCount = iniFile.getIntValue();
1378                         else if (iniFile.isName("kickPushStartRelays"))
1379                                 servMgr->kickPushStartRelays = iniFile.getIntValue();
1380                         else if (iniFile.isName("kickPushInterval"))
1381                         {
1382                                 servMgr->kickPushInterval = iniFile.getIntValue();
1383                                 if (servMgr->kickPushInterval < 60)
1384                                         servMgr->kickPushInterval = 0;
1385                         }
1386                         else if (iniFile.isName("allowConnectPCST"))
1387                                 servMgr->allowConnectPCST = iniFile.getIntValue();
1388                         else if (iniFile.isName("enableGetName"))
1389                                 servMgr->enableGetName = iniFile.getIntValue();
1390
1391                         else if (iniFile.isName("maxRelaysIndexTxt"))                   // for PCRaw (relay)
1392                                 servMgr->maxRelaysIndexTxt = iniFile.getIntValue();
1393
1394                         //JP-Windows
1395                         else if (iniFile.isName("getModulePath"))
1396                                 servMgr->getModulePath = iniFile.getBoolValue();
1397                         else if (iniFile.isName("clearPLS"))
1398                                 servMgr->clearPLS = iniFile.getBoolValue();
1399                         else if (iniFile.isName("writeLogFile"))
1400                                 servMgr->writeLogFile = iniFile.getBoolValue();
1401
1402                         //VP-EX
1403                         else if (iniFile.isName("rootHost2"))
1404                         {
1405                                 if (!PCP_FORCE_YP)
1406                                         servMgr->rootHost2 = iniFile.getStrValue();
1407                         }
1408                         else if (iniFile.isName("autoPort0Kick"))
1409                                 servMgr->autoPort0Kick = iniFile.getBoolValue();
1410                         else if (iniFile.isName("allowOnlyVP"))
1411                                 servMgr->allowOnlyVP = iniFile.getBoolValue();
1412                         else if (iniFile.isName("kickKeepTime"))
1413                                 servMgr->kickKeepTime = iniFile.getIntValue();
1414                         else if (iniFile.isName("vpDebug"))
1415                                 servMgr->vpDebug = iniFile.getBoolValue();
1416                         else if (iniFile.isName("saveIniChannel"))
1417                                 servMgr->saveIniChannel = iniFile.getBoolValue();
1418 #ifdef WIN32
1419                         else if (iniFile.isName("saveGuiPos"))
1420                                 servMgr->saveGuiPos = iniFile.getBoolValue();
1421                         else if (iniFile.isName("guiTop"))
1422                                 winPlace.rcNormalPosition.top = iniFile.getIntValue();
1423                         else if (iniFile.isName("guiBottom"))
1424                                 winPlace.rcNormalPosition.bottom = iniFile.getIntValue();
1425                         else if (iniFile.isName("guiLeft"))
1426                                 winPlace.rcNormalPosition.left = iniFile.getIntValue();
1427                         else if (iniFile.isName("guiRight")){
1428                                 winPlace.rcNormalPosition.right = iniFile.getIntValue();
1429                                 winPlace.length = sizeof(winPlace);
1430                                 winPlace.flags = 0;
1431                                 winPlace.showCmd = 1;
1432                                 winPlace.ptMinPosition.x = -1;
1433                                 winPlace.ptMinPosition.y = -1;
1434                                 winPlace.ptMaxPosition.x = -1;
1435                                 winPlace.ptMaxPosition.y = -1;
1436                                 if (servMgr->saveGuiPos){
1437                                         guiFlg = true;
1438                                 }
1439                         }
1440
1441                         else if (iniFile.isName("topmostGui"))
1442                         {
1443                                 servMgr->topmostGui = iniFile.getBoolValue();
1444                         } else if (iniFile.isName("startWithGui"))
1445                         {
1446                                 servMgr->startWithGui = iniFile.getBoolValue();
1447                         }
1448 #endif
1449
1450                         // debug
1451                         else if (iniFile.isName("logDebug"))
1452                                 showLog |= iniFile.getBoolValue() ? 1<<LogBuffer::T_DEBUG:0;
1453                         else if (iniFile.isName("logErrors"))
1454                                 showLog |= iniFile.getBoolValue() ? 1<<LogBuffer::T_ERROR:0;
1455                         else if (iniFile.isName("logNetwork"))
1456                                 showLog |= iniFile.getBoolValue() ? 1<<LogBuffer::T_NETWORK:0;
1457                         else if (iniFile.isName("logChannel"))
1458                                 showLog |= iniFile.getBoolValue() ? 1<<LogBuffer::T_CHANNEL:0;
1459                         else if (iniFile.isName("pauseLog"))
1460                                 pauseLog = iniFile.getBoolValue();
1461                         else if (iniFile.isName("idleSleepTime"))
1462                                 sys->idleSleepTime = iniFile.getIntValue();
1463                         else if (iniFile.isName("[Server1]"))
1464                                 allowServer1 = readServerSettings(iniFile,allowServer1);
1465                         else if (iniFile.isName("[Server2]"))
1466                                 allowServer2 = readServerSettings(iniFile,allowServer2);
1467                         else if (iniFile.isName("[Filter]"))
1468                         {
1469                                 readFilterSettings(iniFile,filters[numFilters]);
1470
1471                                 if (numFilters < (MAX_FILTERS-1))
1472                                         numFilters++;
1473                         }
1474                         else if (iniFile.isName("[Notify]"))
1475                         {
1476                                 notifyMask = NT_UPGRADE;
1477                                 while (iniFile.readNext())
1478                                 {
1479                                         if (iniFile.isName("[End]"))
1480                                                 break;
1481                                         else if (iniFile.isName("PeerCast"))
1482                                                 notifyMask |= iniFile.getBoolValue()?NT_PEERCAST:0;
1483                                         else if (iniFile.isName("Broadcasters"))
1484                                                 notifyMask |= iniFile.getBoolValue()?NT_BROADCASTERS:0;
1485                                         else if (iniFile.isName("TrackInfo"))
1486                                                 notifyMask |= iniFile.getBoolValue()?NT_TRACKINFO:0;
1487                                 }
1488
1489                         }
1490                         else if (iniFile.isName("[RelayChannel]"))
1491                         {
1492                                 ChanInfo info;
1493                                 bool stayConnected=false;
1494                                 String sourceURL;
1495                                 while (iniFile.readNext())
1496                                 {
1497                                         if (iniFile.isName("[End]"))
1498                                                 break;
1499                                         else if (iniFile.isName("name"))
1500                                                 info.name.set(iniFile.getStrValue());
1501                                         else if (iniFile.isName("id"))
1502                                                 info.id.fromStr(iniFile.getStrValue());
1503                                         else if (iniFile.isName("sourceType"))
1504                                                 info.srcProtocol = ChanInfo::getProtocolFromStr(iniFile.getStrValue());
1505                                         else if (iniFile.isName("contentType"))
1506                                                 info.contentType = ChanInfo::getTypeFromStr(iniFile.getStrValue());
1507                                         else if (iniFile.isName("stayConnected"))
1508                                                 stayConnected = iniFile.getBoolValue();
1509                                         else if (iniFile.isName("sourceURL"))
1510                                                 sourceURL.set(iniFile.getStrValue());
1511                                         else if (iniFile.isName("genre"))
1512                                                 info.genre.set(iniFile.getStrValue());
1513                                         else if (iniFile.isName("contactURL"))
1514                                                 info.url.set(iniFile.getStrValue());
1515                                         else if (iniFile.isName("bitrate"))
1516                                                 info.bitrate = atoi(iniFile.getStrValue());
1517                                         else if (iniFile.isName("tracker"))
1518                                         {
1519                                                 ChanHit hit;
1520                                                 hit.init();
1521                                                 hit.tracker = true;
1522                                                 hit.host.fromStrName(iniFile.getStrValue(),DEFAULT_PORT);
1523                                                 hit.rhost[0] = hit.host;
1524                                                 hit.rhost[1] = hit.host;
1525                                                 hit.chanID = info.id;
1526                                                 hit.recv = true;
1527                                                 chanMgr->addHit(hit);
1528                                         }
1529
1530                                 }
1531                                 if (sourceURL.isEmpty())
1532                                 {
1533                                         chanMgr->createRelay(info,stayConnected);
1534                                 }else
1535                                 {
1536                                         info.bcID = chanMgr->broadcastID;
1537                                         Channel *c = chanMgr->createChannel(info,NULL);
1538                                         if (c)
1539                                                 c->startURL(sourceURL.cstr());
1540                                 }
1541                         } else if (iniFile.isName("[Host]"))
1542                         {
1543                                 Host h;
1544                                 ServHost::TYPE type=ServHost::T_NONE;
1545                                 bool firewalled=false;
1546                                 unsigned int time=0;
1547                                 while (iniFile.readNext())
1548                                 {
1549                                         if (iniFile.isName("[End]"))
1550                                                 break;
1551                                         else if (iniFile.isName("address"))
1552                                                 h.fromStrIP(iniFile.getStrValue(),DEFAULT_PORT);
1553                                         else if (iniFile.isName("type"))
1554                                                 type = ServHost::getTypeFromStr(iniFile.getStrValue());
1555                                         else if (iniFile.isName("time"))
1556                                                 time = iniFile.getIntValue();
1557                                 }
1558                                 servMgr->addHost(h,type,time);
1559
1560                         } else if (iniFile.isName("[ValidBCID]"))
1561                         {
1562                                 BCID *bcid = new BCID();
1563                                 while (iniFile.readNext())
1564                                 {
1565                                         if (iniFile.isName("[End]"))
1566                                                 break;
1567                                         else if (iniFile.isName("id"))
1568                                                 bcid->id.fromStr(iniFile.getStrValue());
1569                                         else if (iniFile.isName("name"))
1570                                                 bcid->name.set(iniFile.getStrValue());
1571                                         else if (iniFile.isName("email"))
1572                                                 bcid->email.set(iniFile.getStrValue());
1573                                         else if (iniFile.isName("url"))
1574                                                 bcid->url.set(iniFile.getStrValue());
1575                                         else if (iniFile.isName("valid"))
1576                                                 bcid->valid = iniFile.getBoolValue();
1577                                 }
1578                                 servMgr->addValidBCID(bcid);
1579                         }
1580                 }       
1581         }
1582
1583         if (!numFilters)
1584                 setFilterDefaults();
1585
1586 }
1587
1588 // --------------------------------------------------
1589 unsigned int ServMgr::numStreams(GnuID &cid, Servent::TYPE tp, bool all)
1590 {
1591         int cnt = 0;
1592         Servent *sv = servents;
1593         while (sv)
1594         {
1595                 if (sv->isConnected())
1596                         if (sv->type == tp)
1597                                 if (sv->chanID.isSame(cid))
1598                                         if (all || !sv->isPrivate())
1599                                                 cnt++;
1600                 sv=sv->next;
1601         }
1602         return cnt;
1603 }
1604 // --------------------------------------------------
1605 unsigned int ServMgr::numStreams(Servent::TYPE tp, bool all)
1606 {
1607         int cnt = 0;
1608         Servent *sv = servents;
1609         while (sv)
1610         {
1611                 if (sv->isConnected())
1612                         if (sv->type == tp)
1613                                 if (all || !sv->isPrivate())
1614                                 {
1615                                         // for PCRaw (relay) start.
1616                                         if(tp == Servent::T_RELAY)
1617                                         {
1618                                                 Channel *ch = chanMgr->findChannelByID(sv->chanID);
1619
1620                                                 // index.txt\82Í\83J\83E\83\93\83g\82µ\82È\82¢
1621                                                 if(!isIndexTxt(ch))
1622                                                         cnt++;
1623                                         }
1624                                         else
1625                                         // for PCRaw (relay) end.
1626                                         {
1627                                                 cnt++;
1628                                         }
1629                                 }
1630                 sv=sv->next;
1631         }
1632         return cnt;
1633 }
1634
1635 // --------------------------------------------------
1636 bool ServMgr::getChannel(char *str,ChanInfo &info, bool relay)
1637 {
1638         // remove file extension (only added for winamp)
1639         //char *ext = strstr(str,".");
1640         //if (ext) *ext = 0;
1641
1642         procConnectArgs(str,info);
1643
1644         WLockBlock wb(&(chanMgr->channellock));
1645
1646         wb.on();
1647         Channel *ch;
1648
1649         ch = chanMgr->findChannelByNameID(info);
1650         if (ch && ch->thread.active)
1651         {
1652
1653                 if (!ch->isPlaying())
1654                 {
1655                         if (relay)
1656                         {
1657                                 ch->info.lastPlayStart = 0; // force reconnect 
1658                                 ch->info.lastPlayEnd = 0; 
1659                         }else
1660                                 return false;
1661                 }
1662                 
1663                 info = ch->info;        // get updated channel info 
1664
1665                 return true;
1666         }else
1667         {
1668                 if (relay)
1669                 {
1670                         wb.off();
1671                         ch = chanMgr->findAndRelay(info);
1672                         if (ch)
1673                         {
1674                                 // \81«Exception point
1675                                 info = ch->info; //get updated channel info 
1676                                 return true;
1677                         }
1678                 }
1679         }
1680
1681         return false;
1682 }
1683 // --------------------------------------------------
1684 int ServMgr::findChannel(ChanInfo &info)
1685 {
1686 #if 0
1687         char idStr[64];
1688         info.id.toStr(idStr);
1689
1690
1691         if (info.id.isSet())
1692         {
1693                 // if we have an ID then try and connect to known hosts carrying channel.
1694                 ServHost sh = getOutgoingServent(info.id);
1695                 addOutgoing(sh.host,info.id,true);
1696         }
1697
1698         GnuPacket pack;
1699
1700         XML xml;
1701         XML::Node *n = info.createQueryXML();
1702         xml.setRoot(n);
1703         pack.initFind(NULL,&xml,servMgr->queryTTL);
1704
1705         addReplyID(pack.id);
1706         int cnt = broadcast(pack,NULL);
1707
1708         LOG_NETWORK("Querying network: %s %s - %d servents",info.name.cstr(),idStr,cnt);
1709
1710         return cnt;
1711 #endif
1712         return 0;
1713 }
1714 // --------------------------------------------------
1715 // add outgoing network connection from string (ip:port format)
1716 bool ServMgr::addOutgoing(Host h, GnuID &netid, bool pri)
1717 {
1718 #if 0
1719         if (h.ip)
1720         {
1721                 if (!findServent(h.ip,h.port,netid))
1722                 {
1723                         Servent *sv = allocServent();
1724                         if (sv)
1725                         {
1726                                 if (pri)
1727                                         sv->priorityConnect = true;
1728                                 sv->networkID = netid;
1729                                 sv->initOutgoing(h,Servent::T_OUTGOING);
1730                                 return true;
1731                         }
1732                 }
1733         }
1734 #endif
1735         return false;
1736 }
1737 // --------------------------------------------------
1738 Servent *ServMgr::findConnection(Servent::TYPE t,GnuID &sid)
1739 {
1740         Servent *sv = servents;
1741         while (sv)
1742         {
1743                 if (sv->isConnected())
1744                         if (sv->type == t)
1745                                 if (sv->remoteID.isSame(sid))                           
1746                                         return sv;
1747                 sv=sv->next;
1748         }
1749         return NULL;
1750 }
1751
1752 // --------------------------------------------------
1753 void ServMgr::procConnectArgs(char *str,ChanInfo &info)
1754 {
1755         char arg[MAX_CGI_LEN];
1756         char curr[MAX_CGI_LEN];
1757
1758         char *args = strstr(str,"?");
1759         if (args)
1760                 *args++=0;
1761
1762         info.initNameID(str);
1763
1764         if (args)
1765         {
1766
1767                 while (args=nextCGIarg(args,curr,arg))
1768                 {
1769                         LOG_DEBUG("cmd: %s, arg: %s",curr,arg);
1770
1771                         if (strcmp(curr,"sip")==0)
1772                         // sip - add network connection to client with channel
1773                         {
1774                                 Host h;
1775                                 h.fromStrName(arg,DEFAULT_PORT);
1776                                 if (addOutgoing(h,servMgr->networkID,true))
1777                                         LOG_NETWORK("Added connection: %s",arg);
1778
1779                         }else if (strcmp(curr,"pip")==0)
1780                         // pip - add private network connection to client with channel
1781                         {
1782                                 Host h;
1783                                 h.fromStrName(arg,DEFAULT_PORT);
1784                                 if (addOutgoing(h,info.id,true))
1785                                         LOG_NETWORK("Added private connection: %s",arg);
1786                         }else if (strcmp(curr,"ip")==0)
1787                         // ip - add hit
1788                         {
1789                                 Host h;
1790                                 h.fromStrName(arg,DEFAULT_PORT);
1791                                 ChanHit hit;
1792                                 hit.init();
1793                                 hit.host = h; 
1794                                 hit.rhost[0] = h;
1795                                 hit.rhost[1].init();
1796                                 hit.chanID = info.id;
1797                                 hit.recv = true;
1798
1799                                 chanMgr->addHit(hit);
1800                         }else if (strcmp(curr,"tip")==0)
1801                         // tip - add tracker hit
1802                         {
1803                                 Host h;
1804                                 h.fromStrName(arg,DEFAULT_PORT);
1805                                 chanMgr->hitlistlock.on();
1806                                 chanMgr->addHit(h,info.id,true);
1807                                 chanMgr->hitlistlock.off();
1808
1809                         }
1810
1811
1812                 }
1813         }
1814 }
1815
1816 // --------------------------------------------------
1817 bool ServMgr::start()
1818 {
1819         char idStr[64];
1820
1821
1822         const char *priv;
1823 #if PRIVATE_BROADCASTER
1824         priv = "(private)";
1825 #else
1826         priv = "";
1827 #endif
1828 #ifdef VERSION_EX
1829         LOG_DEBUG("Peercast %s, %s %s",PCX_VERSTRING_EX,peercastApp->getClientTypeOS(),priv);
1830 #else
1831         LOG_DEBUG("Peercast %s, %s %s",PCX_VERSTRING,peercastApp->getClientTypeOS(),priv);
1832 #endif
1833
1834         sessionID.toStr(idStr);
1835         LOG_DEBUG("SessionID: %s",idStr);
1836
1837         chanMgr->broadcastID.toStr(idStr);
1838         LOG_DEBUG("BroadcastID: %s",idStr);
1839         checkForceIP();
1840
1841
1842         serverThread.func = ServMgr::serverProc;
1843         if (!sys->startThread(&serverThread))
1844                 return false;
1845
1846         idleThread.func = ServMgr::idleProc;
1847         if (!sys->startThread(&idleThread))
1848                 return false;
1849
1850         return true;
1851 }
1852 // --------------------------------------------------
1853 int ServMgr::clientProc(ThreadInfo *thread)
1854 {
1855 #if 0
1856         thread->lock();
1857
1858         GnuID netID;
1859         netID = servMgr->networkID;
1860
1861         while(thread->active)
1862         {
1863                 if (servMgr->autoConnect)
1864                 {
1865                         if (servMgr->needConnections() || servMgr->forceLookup)
1866                         {
1867                                 if (servMgr->needHosts() || servMgr->forceLookup)
1868                                 {
1869                                         // do lookup to find some hosts
1870
1871                                         Host lh;
1872                                         lh.fromStrName(servMgr->connectHost,DEFAULT_PORT);
1873
1874
1875                                         if (!servMgr->findServent(lh.ip,lh.port,netID))
1876                                         {
1877                                                 Servent *sv = servMgr->allocServent();
1878                                                 if (sv)
1879                                                 {
1880                                                         LOG_DEBUG("Lookup: %s",servMgr->connectHost);
1881                                                         sv->networkID = netID;
1882                                                         sv->initOutgoing(lh,Servent::T_LOOKUP);
1883                                                         servMgr->forceLookup = false;
1884                                                 }
1885                                         }
1886                                 }
1887
1888                                 for(int i=0; i<MAX_TRYOUT; i++)
1889                                 {
1890                                         if (servMgr->outUsedFull())
1891                                                 break;
1892                                         if (servMgr->tryFull())
1893                                                 break;
1894
1895
1896                                         ServHost sh = servMgr->getOutgoingServent(netID);
1897
1898                                         if (!servMgr->addOutgoing(sh.host,netID,false))
1899                                                 servMgr->deadHost(sh.host,ServHost::T_SERVENT);
1900                                         sys->sleep(servMgr->tryoutDelay);
1901                                         break;
1902                                 }
1903                         }
1904                 }else{
1905 #if 0
1906                         Servent *s = servMgr->servents;
1907                         while (s)
1908                         {
1909
1910                                 if (s->type == Servent::T_OUTGOING) 
1911                                         s->thread.active = false;
1912                                 s=s->next;
1913                         }
1914 #endif
1915                 }
1916                 sys->sleepIdle();
1917         }
1918         thread->unlock();
1919 #endif
1920         return 0;
1921 }
1922 // -----------------------------------
1923 bool    ServMgr::acceptGIV(ClientSocket *sock)
1924 {
1925         Servent *sv = servents;
1926         while (sv)
1927         {
1928                 if (sv->type == Servent::T_COUT)
1929                 {
1930                         if (sv->acceptGIV(sock))
1931                                 return true;
1932                 }
1933                 sv=sv->next;
1934         }
1935         return false;
1936 }
1937
1938 // -----------------------------------
1939 int ServMgr::broadcastPushRequest(ChanHit &hit, Host &to, GnuID &chanID, Servent::TYPE type)
1940 {
1941         ChanPacket pack;
1942         MemoryStream pmem(pack.data,sizeof(pack.data));
1943         AtomStream atom(pmem);
1944
1945 #ifndef VERSION_EX
1946                 atom.writeParent(PCP_BCST,8);
1947 #else
1948                 atom.writeParent(PCP_BCST,10);
1949 #endif
1950                 atom.writeChar(PCP_BCST_GROUP,PCP_BCST_GROUP_ALL);
1951                 atom.writeChar(PCP_BCST_HOPS,0);
1952                 atom.writeChar(PCP_BCST_TTL,7);
1953                 atom.writeBytes(PCP_BCST_DEST,hit.sessionID.id,16);
1954                 atom.writeBytes(PCP_BCST_FROM,servMgr->sessionID.id,16);
1955                 atom.writeInt(PCP_BCST_VERSION,PCP_CLIENT_VERSION);
1956                 atom.writeInt(PCP_BCST_VERSION_VP,PCP_CLIENT_VERSION_VP);
1957 #ifdef VERSION_EX
1958                 atom.writeBytes(PCP_BCST_VERSION_EX_PREFIX,PCP_CLIENT_VERSION_EX_PREFIX,2);
1959                 atom.writeShort(PCP_BCST_VERSION_EX_NUMBER,PCP_CLIENT_VERSION_EX_NUMBER);
1960 #endif
1961                 atom.writeParent(PCP_PUSH,3);
1962                         atom.writeInt(PCP_PUSH_IP,to.ip);
1963                         atom.writeShort(PCP_PUSH_PORT,to.port);
1964                         atom.writeBytes(PCP_PUSH_CHANID,chanID.id,16);
1965
1966
1967         pack.len = pmem.pos;
1968         pack.type = ChanPacket::T_PCP;
1969
1970
1971         GnuID noID;
1972         noID.clear();
1973
1974         return servMgr->broadcastPacket(pack,noID,servMgr->sessionID,hit.sessionID,type);
1975 }
1976
1977 // --------------------------------------------------
1978 void ServMgr::writeRootAtoms(AtomStream &atom, bool getUpdate)
1979 {
1980         atom.writeParent(PCP_ROOT,5 + (getUpdate?1:0));
1981                 atom.writeInt(PCP_ROOT_UPDINT,chanMgr->hostUpdateInterval);
1982                 atom.writeString(PCP_ROOT_URL,"download.php");
1983                 atom.writeInt(PCP_ROOT_CHECKVER,PCP_ROOT_VERSION);
1984                 atom.writeInt(PCP_ROOT_NEXT,chanMgr->hostUpdateInterval);
1985                 atom.writeString(PCP_MESG_ASCII,rootMsg.cstr());
1986                 if (getUpdate)
1987                         atom.writeParent(PCP_ROOT_UPDATE,0);
1988
1989 }
1990 // --------------------------------------------------
1991 void ServMgr::broadcastRootSettings(bool getUpdate)
1992 {
1993         if (isRoot)
1994         {
1995
1996                 ChanPacket pack;
1997                 MemoryStream mem(pack.data,sizeof(pack.data));
1998                 AtomStream atom(mem);
1999 #ifndef VERSION_EX
2000                         atom.writeParent(PCP_BCST,7);
2001 #else
2002                         atom.writeParent(PCP_BCST,9);
2003 #endif
2004                         atom.writeChar(PCP_BCST_GROUP,PCP_BCST_GROUP_TRACKERS);
2005                         atom.writeChar(PCP_BCST_HOPS,0);
2006                         atom.writeChar(PCP_BCST_TTL,7);
2007                         atom.writeBytes(PCP_BCST_FROM,sessionID.id,16);
2008                         atom.writeInt(PCP_BCST_VERSION,PCP_CLIENT_VERSION);
2009                         atom.writeInt(PCP_BCST_VERSION_VP,PCP_CLIENT_VERSION_VP);
2010 #ifdef VERSION_EX
2011                         atom.writeBytes(PCP_BCST_VERSION_EX_PREFIX,PCP_CLIENT_VERSION_EX_PREFIX,2);
2012                         atom.writeShort(PCP_BCST_VERSION_EX_NUMBER,PCP_CLIENT_VERSION_EX_NUMBER);
2013 #endif
2014                         writeRootAtoms(atom,getUpdate);
2015
2016                 mem.len = mem.pos;
2017                 mem.rewind();
2018                 pack.len = mem.len;
2019
2020                 GnuID noID;
2021                 noID.clear();
2022
2023                 broadcastPacket(pack,noID,servMgr->sessionID,noID,Servent::T_CIN);
2024         }
2025 }
2026 // --------------------------------------------------
2027 int ServMgr::broadcastPacket(ChanPacket &pack,GnuID &chanID,GnuID &srcID, GnuID &destID, Servent::TYPE type)
2028 {
2029         int cnt=0;
2030         
2031         Servent *sv = servents;
2032         while (sv)
2033         {
2034                 if (sv->sendPacket(pack,chanID,srcID,destID,type))
2035                         cnt++;
2036                 sv=sv->next;
2037         }
2038         return cnt;
2039 }
2040
2041 // --------------------------------------------------
2042 int ServMgr::idleProc(ThreadInfo *thread)
2043 {
2044
2045 //      thread->lock();
2046
2047         unsigned int lastPasvFind=0;
2048         unsigned int lastBroadcast=0;
2049
2050
2051         // nothing much to do for the first couple of seconds, so just hang around.
2052         sys->sleep(2000);       
2053
2054         unsigned int lastBWcheck=0;
2055         unsigned int bytesIn=0,bytesOut=0;
2056
2057         unsigned int lastBroadcastConnect = 0;
2058         unsigned int lastRootBroadcast = 0;
2059
2060         unsigned int lastForceIPCheck = 0;
2061
2062         while(thread->active)
2063         {
2064                 stats.update();
2065
2066
2067
2068                 unsigned int ctime = sys->getTime();
2069
2070
2071                 if (!servMgr->forceIP.isEmpty())
2072                 {
2073                         if ((ctime-lastForceIPCheck) > 60)
2074                         {
2075                                 if (servMgr->checkForceIP())
2076                                 {
2077                                         GnuID noID;
2078                                         noID.clear();
2079                                         chanMgr->broadcastTrackerUpdate(noID,true);
2080                                 }
2081                                 lastForceIPCheck = ctime;
2082                         }
2083                 }
2084
2085
2086                 if (chanMgr->isBroadcasting())
2087                 {
2088                         if ((ctime-lastBroadcastConnect) > 30)
2089                         {
2090                                 servMgr->connectBroadcaster();
2091                                 lastBroadcastConnect = ctime;
2092                         }
2093                 }
2094
2095                 if (servMgr->isRoot)
2096                 {
2097                         if ((servMgr->lastIncoming) && ((ctime-servMgr->lastIncoming) > 60*60))
2098                         {
2099                                 peercastInst->saveSettings();
2100                                 sys->exit();
2101                         }
2102
2103                         if ((ctime-lastRootBroadcast) > chanMgr->hostUpdateInterval)
2104                         {
2105                                 servMgr->broadcastRootSettings(true);
2106                                 lastRootBroadcast = ctime;
2107                         }
2108                 }
2109
2110
2111                 // clear dead hits
2112                 chanMgr->clearDeadHits(true);
2113
2114                 if (servMgr->kickPushStartRelays && servMgr->kickPushInterval) //JP-EX
2115                 {
2116                         servMgr->banFirewalledHost();
2117                 }
2118
2119                 if (servMgr->shutdownTimer)
2120                 {
2121                         if (--servMgr->shutdownTimer <= 0)
2122                         {
2123                                 peercastInst->saveSettings();
2124                                 sys->exit();
2125                         }
2126                 }
2127
2128                 // shutdown idle channels
2129                 if (chanMgr->numIdleChannels() > ChanMgr::MAX_IDLE_CHANNELS)
2130                         chanMgr->closeOldestIdle();
2131
2132
2133                 sys->sleep(500);
2134         }
2135
2136         sys->endThread(thread);
2137 //      thread->unlock();
2138         return 0;
2139 }
2140
2141 // --------------------------------------------------
2142 int ServMgr::serverProc(ThreadInfo *thread)
2143 {
2144
2145 //      thread->lock();
2146
2147         Servent *serv = servMgr->allocServent();
2148         Servent *serv2 = servMgr->allocServent();
2149
2150         unsigned int lastLookupTime=0;
2151
2152
2153         while (thread->active)
2154         {
2155
2156                 if (servMgr->restartServer)
2157                 {
2158                         serv->abort();          // force close
2159                         serv2->abort();         // force close
2160                         servMgr->quit();
2161
2162                         servMgr->restartServer = false;
2163                 }
2164
2165                 if (servMgr->autoServe)
2166                 {
2167                         serv->allow = servMgr->allowServer1;
2168                         serv2->allow = servMgr->allowServer2;
2169
2170
2171                         if ((!serv->sock) || (!serv2->sock))
2172                         {
2173                                 LOG_DEBUG("Starting servers");
2174 //                              servMgr->forceLookup = true;
2175
2176                                 //if (servMgr->serverHost.ip != 0)
2177                                 {
2178
2179                                         if (servMgr->forceNormal)
2180                                                 servMgr->setFirewall(ServMgr::FW_OFF);
2181                                         else
2182                                                 servMgr->setFirewall(ServMgr::FW_UNKNOWN);
2183
2184                                         Host h = servMgr->serverHost;
2185
2186                                         if (!serv->sock)
2187                                                 serv->initServer(h);
2188
2189                                         h.port++;
2190                                         if (!serv2->sock)
2191                                                 serv2->initServer(h);
2192
2193
2194                                 }
2195                         }
2196                 }else{
2197                         // stop server
2198                         serv->abort();          // force close
2199                         serv2->abort();         // force close
2200
2201                         // cancel incoming connectuions
2202                         Servent *s = servMgr->servents;
2203                         while (s)
2204                         {
2205                                 if (s->type == Servent::T_INCOMING)
2206                                         s->thread.active = false;
2207                                 s=s->next;
2208                         }
2209
2210                         servMgr->setFirewall(ServMgr::FW_ON);
2211                 }
2212                         
2213                 sys->sleepIdle();
2214
2215         }
2216
2217         sys->endThread(thread);
2218 //      thread->unlock();
2219         return 0;
2220 }
2221
2222 // -----------------------------------
2223 void    ServMgr::setMaxRelays(int max)
2224 {
2225         if (max < MIN_RELAYS)
2226                 max = MIN_RELAYS;
2227         maxRelays = max;
2228 }
2229
2230 // -----------------------------------
2231 XML::Node *ServMgr::createServentXML()
2232 {
2233
2234         return new XML::Node("servent agent=\"%s\" ",PCX_AGENT);
2235 }
2236
2237 // --------------------------------------------------
2238 const char *ServHost::getTypeStr(TYPE t)
2239 {
2240         switch(t)
2241         {
2242                 case T_NONE: return "NONE";
2243                 case T_STREAM: return "STREAM";
2244                 case T_CHANNEL: return "CHANNEL";
2245                 case T_SERVENT: return "SERVENT";
2246                 case T_TRACKER: return "TRACKER";
2247         }
2248         return "UNKNOWN";
2249 }
2250 // --------------------------------------------------
2251 ServHost::TYPE ServHost::getTypeFromStr(const char *s)
2252 {
2253         if (stricmp(s,"NONE")==0)
2254                 return T_NONE;
2255         else if (stricmp(s,"SERVENT")==0)
2256                 return T_SERVENT;
2257         else if (stricmp(s,"STREAM")==0)
2258                 return T_STREAM;
2259         else if (stricmp(s,"CHANNEL")==0)
2260                 return T_CHANNEL;
2261         else if (stricmp(s,"TRACKER")==0)
2262                 return T_TRACKER;
2263
2264         return T_NONE;
2265 }
2266
2267
2268 // --------------------------------------------------
2269 bool    ServFilter::writeVariable(Stream &out, const String &var)
2270 {
2271         char buf[1024];
2272
2273         if (var == "network")
2274                 strcpy(buf,(flags & F_NETWORK)?"1":"0");
2275         else if (var == "private")
2276                 strcpy(buf,(flags & F_PRIVATE)?"1":"0");
2277         else if (var == "direct")
2278                 strcpy(buf,(flags & F_DIRECT)?"1":"0");
2279         else if (var == "banned")
2280                 strcpy(buf,(flags & F_BAN)?"1":"0");
2281         else if (var == "ip")
2282                 host.IPtoStr(buf);
2283         else
2284                 return false;
2285
2286
2287         out.writeString(buf);
2288         return true;
2289 }
2290 // --------------------------------------------------
2291 bool    BCID::writeVariable(Stream &out, const String &var)
2292 {
2293         char buf[1024];
2294
2295         if (var == "id")
2296                 id.toStr(buf);
2297         else if (var == "name")
2298                 strcpy(buf,name.cstr());
2299         else if (var == "email")
2300                 strcpy(buf,email.cstr());
2301         else if (var == "url")
2302                 strcpy(buf,url.cstr());
2303         else if (var == "valid")
2304                 strcpy(buf,valid?"Yes":"No");
2305         else
2306                 return false;
2307
2308
2309         out.writeString(buf);
2310         return true;
2311 }
2312
2313
2314 // --------------------------------------------------
2315 bool ServMgr::writeVariable(Stream &out, const String &var)
2316 {
2317         char buf[1024];
2318         String str;
2319
2320         if (var == "version")
2321 #ifdef VERSION_EX
2322                 strcpy(buf,PCX_VERSTRING_EX);
2323 #else
2324                 strcpy(buf,PCX_VERSTRING);
2325 #endif
2326         else if (var == "uptime")
2327         {
2328                 str.setFromStopwatch(getUptime());
2329                 str.convertTo(String::T_HTML);
2330                 strcpy(buf,str.cstr());
2331         }else if (var == "numRelays")
2332                 sprintf(buf,"%d",numStreams(Servent::T_RELAY,true));
2333         else if (var == "numDirect")
2334                 sprintf(buf,"%d",numStreams(Servent::T_DIRECT,true));
2335         else if (var == "totalConnected")
2336                 sprintf(buf,"%d",totalConnected());
2337         else if (var == "numServHosts")
2338                 sprintf(buf,"%d",numHosts(ServHost::T_SERVENT));                
2339         else if (var == "numServents")
2340                 sprintf(buf,"%d",numServents());                
2341         else if (var == "serverPort")
2342                 sprintf(buf,"%d",serverHost.port);              
2343         else if (var == "serverIP")
2344                 serverHost.IPtoStr(buf);
2345         else if (var == "ypAddress")
2346                 strcpy(buf,rootHost.cstr());
2347         else if (var == "password")
2348                 strcpy(buf,password);
2349         else if (var == "isFirewalled")
2350                 sprintf(buf,"%d",getFirewall()==FW_ON?1:0);
2351         else if (var == "firewallKnown")
2352                 sprintf(buf,"%d",getFirewall()==FW_UNKNOWN?0:1);
2353         else if (var == "rootMsg")
2354                 strcpy(buf,rootMsg);
2355         else if (var == "isRoot")
2356                 sprintf(buf,"%d",isRoot?1:0);
2357         else if (var == "isPrivate")
2358                 sprintf(buf,"%d",(PCP_BROADCAST_FLAGS&1)?1:0);
2359         else if (var == "forceYP")
2360                 sprintf(buf,"%d",PCP_FORCE_YP?1:0);
2361         else if (var == "refreshHTML")
2362                 sprintf(buf,"%d",refreshHTML?refreshHTML:0x0fffffff);
2363         else if (var == "maxRelays")
2364                 sprintf(buf,"%d",maxRelays);
2365         else if (var == "maxDirect")
2366                 sprintf(buf,"%d",maxDirect);
2367         else if (var == "maxBitrateOut")
2368                 sprintf(buf,"%d",maxBitrateOut);
2369         else if (var == "maxControlsIn")
2370                 sprintf(buf,"%d",maxControl);
2371         else if (var == "maxServIn")
2372                 sprintf(buf,"%d",maxServIn);
2373         else if (var == "numFilters")
2374                 sprintf(buf,"%d",numFilters+1);
2375         else if (var == "maxPGNUIn")
2376                 sprintf(buf,"%d",maxGnuIncoming);
2377         else if (var == "minPGNUIn")
2378                 sprintf(buf,"%d",minGnuIncoming);
2379         else if (var == "numActive1")
2380                 sprintf(buf,"%d",numActiveOnPort(serverHost.port));
2381         else if (var == "numActive2")
2382                 sprintf(buf,"%d",numActiveOnPort(serverHost.port+1));
2383         else if (var == "numPGNU")
2384                 sprintf(buf,"%d",numConnected(Servent::T_PGNU));
2385         else if (var == "numCIN")
2386                 sprintf(buf,"%d",numConnected(Servent::T_CIN));
2387         else if (var == "numCOUT")
2388                 sprintf(buf,"%d",numConnected(Servent::T_COUT));
2389         else if (var == "numIncoming")
2390                 sprintf(buf,"%d",numActive(Servent::T_INCOMING));
2391         else if (var == "numValidBCID")
2392         {
2393                 int cnt = 0;
2394                 BCID *bcid = validBCID;
2395                 while (bcid)
2396                 {
2397                         cnt++;
2398                         bcid=bcid->next;
2399                 }
2400                 sprintf(buf,"%d",cnt);
2401         }
2402
2403         else if (var == "disabled")
2404                 sprintf(buf,"%d",isDisabled);
2405
2406         // JP-EX
2407         else if (var.startsWith("autoRelayKeep")) {
2408                 if (var == "autoRelayKeep.0")
2409                         strcpy(buf, (autoRelayKeep == 0) ? "1":"0");
2410                 else if (var == "autoRelayKeep.1")
2411                         strcpy(buf, (autoRelayKeep == 1) ? "1":"0");
2412                 else if (var == "autoRelayKeep.2")
2413                         strcpy(buf, (autoRelayKeep == 2) ? "1":"0");
2414         } else if (var == "autoMaxRelaySetting")
2415                 sprintf(buf,"%d",autoMaxRelaySetting);
2416         else if (var == "autoBumpSkipCount")
2417                 sprintf(buf,"%d",autoBumpSkipCount);
2418         else if (var == "kickPushStartRelays")
2419                 sprintf(buf,"%d",kickPushStartRelays);
2420         else if (var == "kickPushInterval")
2421                 sprintf(buf,"%d",kickPushInterval);
2422         else if (var == "allowConnectPCST")
2423                 strcpy(buf, (allowConnectPCST == 1) ? "1":"0");
2424         else if (var == "enableGetName")
2425                 strcpy(buf, (enableGetName == 1)? "1":"0");
2426
2427         // VP-EX
2428         else if (var == "ypAddress2")
2429                 strcpy(buf,rootHost2.cstr());
2430         else if (var.startsWith("autoPort0Kick")) {
2431                 if (var == "autoPort0Kick.0")
2432                         strcpy(buf, (autoPort0Kick == 0) ? "1":"0");
2433                 else if (var == "autoPort0Kick.1")
2434                         strcpy(buf, (autoPort0Kick == 1) ? "1":"0");
2435         }
2436         else if (var.startsWith("allowOnlyVP")) {
2437                 if (var == "allowOnlyVP.0")
2438                         strcpy(buf, (allowOnlyVP == 0) ? "1":"0");
2439                 else if (var == "allowOnlyVP.1")
2440                         strcpy(buf, (allowOnlyVP == 1) ? "1":"0");
2441         }
2442         else if (var == "kickKeepTime")
2443                 sprintf(buf, "%d",kickKeepTime);
2444
2445         else if (var == "serverPort1")
2446                 sprintf(buf,"%d",serverHost.port);
2447         else if (var == "serverLocalIP")
2448         {
2449                 Host lh(ClientSocket::getIP(NULL),0);
2450                 char ipStr[64];
2451                 lh.IPtoStr(ipStr);
2452                 strcpy(buf,ipStr);
2453         }else if (var == "upgradeURL")
2454                 strcpy(buf,servMgr->downloadURL);
2455         else if (var == "serverPort2")
2456                 sprintf(buf,"%d",serverHost.port+1);
2457         else if (var.startsWith("allow."))
2458         {
2459                 if (var == "allow.HTML1")
2460                         strcpy(buf,(allowServer1&Servent::ALLOW_HTML)?"1":"0");
2461                 else if (var == "allow.HTML2")
2462                         strcpy(buf,(allowServer2&Servent::ALLOW_HTML)?"1":"0");
2463                 else if (var == "allow.broadcasting1")
2464                         strcpy(buf,(allowServer1&Servent::ALLOW_BROADCAST)?"1":"0");
2465                 else if (var == "allow.broadcasting2")
2466                         strcpy(buf,(allowServer2&Servent::ALLOW_BROADCAST)?"1":"0");
2467                 else if (var == "allow.network1")
2468                         strcpy(buf,(allowServer1&Servent::ALLOW_NETWORK)?"1":"0");
2469                 else if (var == "allow.direct1")
2470                         strcpy(buf,(allowServer1&Servent::ALLOW_DIRECT)?"1":"0");
2471         }else if (var.startsWith("auth."))
2472         {
2473                 if (var == "auth.useCookies")
2474                         strcpy(buf,(authType==AUTH_COOKIE)?"1":"0");
2475                 else if (var == "auth.useHTTP")
2476                         strcpy(buf,(authType==AUTH_HTTPBASIC)?"1":"0");
2477                 else if (var == "auth.useSessionCookies")
2478                         strcpy(buf,(cookieList.neverExpire==false)?"1":"0");
2479
2480         }else if (var.startsWith("log."))
2481         {
2482                 if (var == "log.debug")
2483                         strcpy(buf,(showLog&(1<<LogBuffer::T_DEBUG))?"1":"0");
2484                 else if (var == "log.errors")
2485                         strcpy(buf,(showLog&(1<<LogBuffer::T_ERROR))?"1":"0");
2486                 else if (var == "log.gnet")
2487                         strcpy(buf,(showLog&(1<<LogBuffer::T_NETWORK))?"1":"0");
2488                 else if (var == "log.channel")
2489                         strcpy(buf,(showLog&(1<<LogBuffer::T_CHANNEL))?"1":"0");
2490                 else
2491                         return false;
2492         }else if (var == "test")
2493         {
2494                 out.writeUTF8(0x304b);          
2495                 out.writeUTF8(0x304d);          
2496                 out.writeUTF8(0x304f);          
2497                 out.writeUTF8(0x3051);          
2498                 out.writeUTF8(0x3053);  
2499
2500                 out.writeUTF8(0x0041);  
2501                 out.writeUTF8(0x0042);  
2502                 out.writeUTF8(0x0043);  
2503                 out.writeUTF8(0x0044);  
2504
2505                 out.writeChar('a');
2506                 out.writeChar('b');
2507                 out.writeChar('c');
2508                 out.writeChar('d');
2509                 return true;
2510
2511         }else if (var == "maxRelaysIndexTxt")           // for PCRaw (relay)
2512                 sprintf(buf, "%d", maxRelaysIndexTxt);
2513         else
2514                 return false;
2515
2516         out.writeString(buf);
2517         return true;
2518 }
2519 // --------------------------------------------------
2520 //JP-EX
2521 bool ServMgr::isCheckPushStream()
2522 {
2523         if (servMgr->kickPushStartRelays)
2524                 if (servMgr->numStreams(Servent::T_RELAY,false)>=(servMgr->kickPushStartRelays-1))
2525                                 return true;
2526
2527         return false;
2528 }
2529 // --------------------------------------------------
2530 //JP-EX
2531 void ServMgr::banFirewalledHost()
2532 {
2533         unsigned int kickpushtime = sys->getTime();
2534         if ((kickpushtime-servMgr->kickPushTime) > servMgr->kickPushInterval)
2535         {
2536                 servMgr->kickPushTime = kickpushtime;
2537                 Servent *s = servMgr->servents;
2538                 LOG_DEBUG("Servent scan start.");
2539                 while (s)
2540                 {
2541                         if (s->type != Servent::T_NONE)
2542                         {
2543                                 Host h = s->getHost();
2544                                 int ip = h.ip;
2545                                 int port = h.port;
2546                                 Host h2(ip,port);
2547                                 unsigned int tnum = 0;
2548
2549                                 if (s->lastConnect)
2550                                         tnum = sys->getTime() - s->lastConnect;
2551                                 if ((s->type==Servent::T_RELAY) && (s->status==Servent::S_CONNECTED) && (tnum>servMgr->kickPushInterval))
2552                                 {                                               
2553 /*                                      ChanHitList *hits[ChanMgr::MAX_HITLISTS];
2554                                         int numHits=0;
2555                                         for(int i=0; i<ChanMgr::MAX_HITLISTS; i++)
2556                                         {
2557                                                 ChanHitList *chl = &chanMgr->hitlists[i];
2558                                                 if (chl->isUsed())
2559                                                         hits[numHits++] = chl;
2560                                         }
2561
2562                                         bool isfw = false;
2563                                         int numRelay = 0;
2564                                         if (numHits) 
2565                                         {
2566                                                 for(int k=0; k<numHits; k++)
2567                                                 {
2568                                                         ChanHitList *chl = hits[k];
2569                                                         if (chl->isUsed())
2570                                                         {
2571                                                                 for (int j=0; j<ChanHitList::MAX_HITS; j++ )
2572                                                                 {
2573                                                                         ChanHit *hit = &chl->hits[j];
2574                                                                         if (hit->host.isValid() && (h2.ip == hit->host.ip))
2575                                                                         {
2576                                                                                 if (hit->firewalled)
2577                                                                                         isfw = true;
2578                                                                                 numRelay = hit->numRelays;
2579                                                                         }
2580                                                                 }
2581                                                         }
2582                                                 }
2583                                         }
2584                                         if ((isfw==true) && (numRelay==0))
2585                                         {
2586                                                 char hostName[256];
2587                                                 h2.toStr(hostName);
2588                                                 if (servMgr->isCheckPushStream())
2589                                                 {
2590                                                         s->thread.active = false;
2591                                                         LOG_ERROR("Stop firewalled Servent : %s",hostName);
2592                                                 }
2593                                         }*/
2594
2595                                         chanMgr->hitlistlock.on();
2596                                         ChanHitList *chl = chanMgr->findHitListByID(s->chanID);
2597                                         if (chl){
2598                                                 ChanHit *hit = chl->hit;
2599                                                 while(hit){
2600                                                         if ((hit->numHops == 1) && hit->host.isValid() && (h2.ip == hit->host.ip) && hit->firewalled /*&& !hit->numRelays*/)
2601                                                         {
2602                                                                 char hostName[256];
2603                                                                 h2.toStr(hostName);
2604                                                                 if (servMgr->isCheckPushStream())
2605                                                                 {
2606                                                                         s->thread.active = false;
2607                                                                         LOG_ERROR("Stop firewalled Servent : %s",hostName);
2608                                                                 }
2609                                                         }
2610                                                         hit = hit->next;
2611                                                 }
2612
2613                                         }
2614                                         chanMgr->hitlistlock.off();
2615
2616
2617                                 }
2618                         }
2619                         s=s->next;
2620                 }
2621                 LOG_DEBUG("Servent scan finished.");
2622         }
2623 }
2624
2625 // --------------------------------------------------
2626 #if 0
2627 static ChanHit *findServentHit(Servent *s)
2628 {
2629         ChanHitList *chl = chanMgr->findHitListByID(s->chanID);
2630         Host h = s->getHost();
2631
2632         if (chl)
2633         {
2634                 ChanHit *hit = chl->hit;
2635                 while (hit)
2636                 {
2637                         if ((hit->numHops == 1) && hit->host.isValid() && (h.ip == hit->host.ip))
2638                                 return hit;
2639                         hit = hit->next;
2640                 }
2641         }
2642         return NULL;
2643 }
2644 #endif
2645 // --------------------------------------------------
2646 int ServMgr::kickUnrelayableHost(GnuID &chid, ChanHit &sendhit)
2647 {
2648         Servent *ks = NULL;
2649         Servent *s = servMgr->servents;
2650
2651         while (s)
2652         {
2653                 if (s->type == Servent::T_RELAY && s->chanID.isSame(chid) && !s->isPrivate())
2654                 {
2655                         Host h = s->getHost();
2656
2657                         ChanHit hit = s->serventHit;
2658                         if (!hit.relay && hit.numRelays == 0)
2659                         {
2660                                 char hostName[256];
2661                                 h.toStr(hostName);
2662                                 //s->thread.active = false;
2663                                 LOG_DEBUG("unrelayable Servent : %s",hostName);
2664                                 if (!ks || s->lastConnect < ks->lastConnect) // elder servent
2665                                         ks = s;
2666                         }
2667                 }
2668                 s = s->next;
2669         }
2670
2671         if (ks)
2672         {
2673                 if (sendhit.rhost[0].port)
2674                 {
2675                         ChanPacket pack;
2676                         MemoryStream mem(pack.data,sizeof(pack.data));
2677                         AtomStream atom(mem);
2678                         sendhit.writeAtoms(atom, chid);
2679                         pack.len = mem.pos;
2680                         pack.type = ChanPacket::T_PCP;
2681                         GnuID noID;
2682                         noID.clear();
2683
2684                         ks->sendPacket(pack, chid, noID, noID, Servent::T_RELAY);
2685                 }
2686
2687                 ks->setStatus(Servent::S_CLOSING);
2688                 ks->thread.active = false;
2689
2690                 char hostName[256];
2691                 ks->getHost().toStr(hostName);
2692
2693                 LOG_DEBUG("Stop unrelayable Servent : %s",hostName);
2694
2695                 return 1;
2696         }
2697
2698         return 0;
2699 }