a valid decryption is obtained. After that, the decryption sticks to that
particular connection until next channel switch.
-The network code supports dialup on demand. To use this you have to provide an
-external script to connect/disconnect your dialup link. Use commandline option
--d to set the script name and enable the feature, e.g. "-d dialup.sh". See the
-example script "examples/dialup.sh.example". The network is brought up as soon
-as an server connection is requested. All server connections are disconnected if
-they are idle too long (normaly after 120 seconds). The network is brought down
-after the last connection has terminated and an additional network timeout has
-expired. The network timeout is configurable with the commandline option -t and
-defaults to 60 seconds, e.g. "-t 120".
-
Summary of commandline options
------------------------------
-B N --budget=N forces DVB device N to budget mode (using FFdecsa)
--d CMD --dialup=CMD call CMD to start/stop dialup-network
- (default: none)
--t SECS --timeout=SECS shutdown timeout for dialup-network
- (default: 60 secs)
#define DEFAULT_READWRITE_TIMEOUT 3*1000 // ms
#define DEFAULT_IDLE_TIMEOUT 120*1000 // ms
-const char *netscript=0;
-int netTimeout=60*1000; // timeout for shutting down dialup-network
-
// -- cNetWatcher ---------------------------------------------------------------
class cNetWatcher : protected cThread {
private:
- int count;
- cTimeMs down;
- bool netup, downDelay;
cSimpleList<cNetSocket> socks;
- //
- int RunCommand(const char *cmd, const char *state);
protected:
virtual void Action(void);
public:
~cNetWatcher();
void Up(cNetSocket *so);
void Down(cNetSocket *so);
- void Block(void) { Lock(); }
- void Unblock(void) { Unlock(); }
};
static cNetWatcher nw;
cNetWatcher::cNetWatcher(void)
:cThread("Netwatcher")
-{
- count=0; netup=downDelay=false;
-}
+{}
cNetWatcher::~cNetWatcher()
{
Cancel(2);
Lock();
- if(netup) RunCommand(netscript,"down");
cNetSocket *so;
while((so=socks.First())) socks.Del(so,false);
Unlock();
Lock();
socks.Add(so);
if(!Active()) Start();
- if(netscript) {
- downDelay=false; netup=true;
- RunCommand(netscript,"up");
- count++;
- PRINTF(L_CORE_NET,"netwatch up (%d)",count);
- }
- else PRINTF(L_CORE_NET,"netwatch up");
Unlock();
}
{
Lock();
socks.Del(so,false);
- if(netscript) {
- if(--count==0) {
- downDelay=true;
- down.Set(netTimeout);
- }
- PRINTF(L_CORE_NET,"netwatch down (%d)",count);
- }
- else PRINTF(L_CORE_NET,"netwatch down");
Unlock();
}
while(Running()) {
sleep(1);
Lock();
- if(downDelay && down.TimedOut()) {
- PRINTF(L_CORE_NET,"netdown timeout expired");
- if(netup) {
- RunCommand(netscript,"down");
- netup=false;
- }
- downDelay=false;
- }
for(cNetSocket *so=socks.First(); so;) {
cNetSocket *next=socks.Next(so);
so->Lock();
}
}
-int cNetWatcher::RunCommand(const char *cmd, const char *state)
-{
- char *tmp=bprintf("%s %s",cmd,state);
- PRINTF(L_CORE_NET,"netwatch cmd exec '%s'",tmp);
- int res=SystemExec(tmp);
- free(tmp);
- return res;
-}
-
// -- cNetSocket ------------------------------------------------------------------
cNetSocket::cNetSocket(void)
{
- hostname=0; sd=-1; udp=connected=netup=quietlog=false;
+ hostname=0; sd=-1; udp=connected=quietlog=false;
conTimeout=DEFAULT_CONNECT_TIMEOUT; rwTimeout=DEFAULT_READWRITE_TIMEOUT;
idleTimeout=DEFAULT_IDLE_TIMEOUT;
}
bool cNetSocket::Connect(const char *Hostname, int Port, int timeout)
{
- nw.Block();
Lock();
Disconnect();
if(Hostname) {
hostname=strdup(Hostname); port=Port;
}
if(timeout<0) timeout=conTimeout;
- nw.Up(this); netup=true;
- nw.Unblock();
struct sockaddr_in socketAddr;
if(GetAddr(&socketAddr,hostname,port) && (sd=GetSocket(udp))>=0) {
if(!quietlog) PRINTF(L_CORE_NET,"connecting to %s:%d/%s (%d.%d.%d.%d)",
}
else PRINTF(L_GEN_ERROR,"socket: connect failed: %s",*StrError(errno));
- if(connected) { Activity(); Unlock(); return true; }
+ if(connected) { Activity(); nw.Up(this); Unlock(); return true; }
}
Unlock();
Disconnect();
bool cNetSocket::Bind(const char *Hostname, int Port)
{
- nw.Block();
Lock();
Disconnect();
if(Hostname) {
free(hostname);
hostname=strdup(Hostname); port=Port;
}
- nw.Up(this); netup=true;
- nw.Unblock();
struct sockaddr_in socketAddr;
if(GetAddr(&socketAddr,hostname,port) && (sd=GetSocket(udp))>=0) {
if(!quietlog) PRINTF(L_CORE_NET,"socket: binding to %s:%d/%s (%d.%d.%d.%d)",
do { r=bind(sd,(struct sockaddr *)&socketAddr,sizeof(socketAddr)); } while(r<0 && errno==EINTR);
if(r==0) {
connected=true;
- Activity(); Unlock();
+ Activity(); nw.Up(this); Unlock();
return true;
}
else PRINTF(L_GEN_ERROR,"socket: bind failed: %s",*StrError(errno));
void cNetSocket::Disconnect(void)
{
- nw.Block();
cMutexLock lock(this);
+ nw.Down(this);
if(sd>=0) { close(sd); sd=-1; }
quietlog=connected=false;
- if(netup) { nw.Down(this); netup=false; }
- nw.Unblock();
}
void cNetSocket::Flush(void)
free(help_str); // for easier orientation, this is column 80|
help_str=bprintf( " -B N --budget=N forces DVB device N to budget mode (using FFdecsa)\n"
- " -d CMD --dialup=CMD call CMD to start/stop dialup-network\n"
- " (default: %s)\n"
- " -t SECS --timeout=SECS shutdown timeout for dialup-network\n"
- " (default: %d secs)\n",
- "none",netTimeout/1000
);
return help_str;
}
{ "inverse-cd", no_argument, NULL, 'I' },
{ "inverse-rst", no_argument, NULL, 'R' },
{ "clock", optional_argument, NULL, 'C' },
- { "dialup", required_argument, NULL, 'd' },
{ "external-au", required_argument, NULL, 'E' },
{ "budget", required_argument, NULL, 'B' },
{ NULL }
};
int c, option_index=0;
- while((c=getopt_long(argc,argv,"d:s:t:B:C:E:IR",long_options,&option_index))!=-1) {
+ while((c=getopt_long(argc,argv,"s:B:C:E:IR",long_options,&option_index))!=-1) {
switch (c) {
case 'I':
case 'R':
case 'C':
case 's': fprintf(stderr,"smartcard commandline options were removed. use cardslot.conf\n"); return false;
- case 'd': netscript=optarg; break;
- case 't': netTimeout=atoi(optarg)*1000; break;
case 'E': externalAU=optarg; break;
case 'B': cScDvbDevice::SetForceBudget(atoi(optarg)); break;
default: return false;