summaryrefslogtreecommitdiff
path: root/noncore/settings/networksettings2/bluetooth/bluetoothBNEPrun.cpp
blob: 24e4b7b0f42ffbd70171976a2213ea2206543bcc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
#include <qfile.h>
#include <qfileinfo.h>
#include <qtextstream.h>
#include <resources.h>
#include "bluetoothBNEPrun.h"

QDict<QString> *     BluetoothBNEPRun::PANConnections = 0;

void BluetoothBNEPRun::detectState( NodeCollection * NC ) { 
    // unavailable : no card found
    // available : card found and assigned to us or free
    // up : card found and assigned to us and up
    QString S = QString( "/tmp/profile-%1.up" ).arg(NC->number());
    System & Sys = NSResources->system();
    InterfaceInfo * Run;
    QFile F( S );

    Log(("Detecting for %s\n", NC->name().latin1() ));

    if( F.open( IO_ReadOnly ) ) {
      // could open file -> read interface and assign
      QString X;
      bool accepted = 0;
      QTextStream TS(&F);
      X = TS.readLine();
      Log(("%s exists : %s\n", S.latin1(), X.latin1() ));
      // find interface
      if( handlesInterface( X ) ) {

        Log(("Handles interface %s, PANC %p\n", X.latin1(), PANConnections ));
        if( PANConnections == 0 ) {
          // load connections that are active
          // format : bnep0 00:60:57:02:71:A2 PANU
          FILE * OutputOfCmd = popen( "pand --show", "r" ) ;

          PANConnections = new QDict<QString>;

          if( OutputOfCmd ) {
            char ch;
            // could fork
            // read all data
            QString Line =  "";
            while( 1 ) {
              if( fread( &ch, 1, 1, OutputOfCmd ) < 1 ) {
                // eof
                break;
              }
              if( ch == '\n' || ch == '\r' ) {
                if( ! Line.isEmpty() ) {
                  if( Line.startsWith( "bnep" ) ) {
                    QStringList SL = QStringList::split( " ", Line );
                    Log(("Detected PAN %s %s\n", 
                      SL[0].latin1(), SL[1].latin1() ));
                    PANConnections->insert( SL[0], new QString(SL[1]));
                  }
                  Line="";
                }
              } else {
                Line += ch;
              }
            }
          }

          pclose( OutputOfCmd );
        }

        // check if this runtime allows connection to node
        if( ! Data.AllowAll ) {
          // has addresses
          for ( QStringList::Iterator it = Data.BDAddress.begin(); 
                ! accepted && it != Data.BDAddress.end(); 
                ++ it ) {
            for( QDictIterator<QString> it2( *(PANConnections) );
                 it2.current();
                 ++ it2 ) {
              if( X == it2.currentKey() &&
                  (*it) == *(it2.current()) 
                ) {
                // found
                Log(("%s accepts connections to %s\n",
                    NC->name().latin1(),
                    it2.current()->latin1() ));
                accepted = 1;
                break;
              }
            }
          }
        } else {
          Log(("%s accepts any connection\n", NC->name().latin1() ));
          // accept any
          accepted = 1;
        }

        if( accepted ) {
          // matches and is allowed for this node
          for( QDictIterator<InterfaceInfo> It(Sys.interfaces());
               It.current();
               ++It ) {
            Run = It.current();
            if( X == Run->Name ) {
              Log(("%s Assigned %p\n", NC->name().latin1(), Run ));
              Run->assignNode( netNode() );
              assignInterface( Run );
              NC->setCurrentState( IsUp );
              return;
            }
          }
        }
      }
    } 

    Log(("Assigned %p\n", assignedInterface() ));
    if( ( Run = assignedInterface() ) ) {
      // we already have an interface assigned -> still present ?
      if( ! Run->IsUp ) {
        // usb is still free -> keep assignment
        NC->setCurrentState( Available );
        return;
      } // else interface is up but NOT us -> some other profile
    }

    // nothing (valid) assigned to us
    assignInterface( 0 );

    // find possible interface
    for( QDictIterator<InterfaceInfo> It(Sys.interfaces());
         It.current();
         ++It ) {
      Run = It.current();

      Log(("%s %d %d=%d %d\n",
          Run->Name.latin1(),
          handlesInterface( Run->Name ),
              Run->CardType, ARPHRD_ETHER,
              ! Run->IsUp ));

      if( handlesInterface( Run->Name ) &&
          Run->CardType == ARPHRD_ETHER &&
          ! Run->IsUp
        ) {
        Log(("Released(OFF)\n" ));
        // proper type, and Not UP -> free
        NC->setCurrentState( Off );
        return;
      }
    }
    // no free found
    Log(("None available\n" ));

    NC->setCurrentState( Unavailable );
}

bool BluetoothBNEPRun::setState( NodeCollection * NC, Action_t A, bool  ) {

    // we only handle activate and deactivate
    switch( A ) {
      case Activate :
        { 
          if( NC->currentState() != Off ) {
            return 0;
          }
          InterfaceInfo * N = getInterface();
          if( ! N ) {
            // no interface available
            NC->setCurrentState( Unavailable );
            return 0;
          }
          // because we were OFF the interface
          // we get back is NOT assigned
          N->assignNode( netNode() );
          assignInterface( N );
          Log(("Assing %p\n", N ));
          NC->setCurrentState( Available );
          return 1;
        }
      case Deactivate :
        if( NC->currentState() == IsUp ) {
          // bring down first
          if( ! connection()->setState( Down ) )
            // could not ...
            return 0;
        } else if( NC->currentState() != Available ) {
          return 1;
        }
        assignedInterface()->assignNode( 0 ); // release
        assignInterface( 0 );
        NC->setCurrentState( Off );
        return 1;
      default :
        // FT
        break;
    }
    return 0;
}

bool BluetoothBNEPRun::canSetState( State_t Curr , Action_t A ) {
    // we only handle up down activate and deactivate
    switch( A ) {
      case Activate :
        { // at least available 
          if( Curr == Available ) {
            return 1;
          }
          // or we can make one available
          InterfaceInfo * N = getInterface();
          if( ! N || N->assignedNode() != 0 ) {
            // non available or assigned
            return 0;
          }
          return 1;
        }
      case Deactivate :
        return ( Curr >= Available );
      default :
        // FT
        break;
    }
    return 0;
}

// get interface that is free or assigned to us
InterfaceInfo * BluetoothBNEPRun::getInterface( void ) {

    System & S = NSResources->system();
    InterfaceInfo * best = 0, * Run;

    for( QDictIterator<InterfaceInfo> It(S.interfaces());
         It.current();
         ++It ) {
      Run = It.current();
      if( handlesInterface( Run->Name ) &&
          Run->CardType == ARPHRD_ETHER
        ) {
        // this is a bluetooth card
        if( Run->assignedNode() == netNode() ) {
          // assigned to us
          return Run;
        } else if( Run->assignedNode() == 0 ) {
          // free
          best = Run;
        }
      }
    }
    return best; // can be 0
}

bool BluetoothBNEPRun::handlesInterface( const QString & S ) {
    return Pat.match( S ) >= 0;
}