/[cvs]/nfo/php/libs/org.netfrag.glib/DataSource/Proxy/XMLRPC.php
ViewVC logotype

Diff of /nfo/php/libs/org.netfrag.glib/DataSource/Proxy/XMLRPC.php

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.3 by joko, Thu Mar 27 16:05:01 2003 UTC revision 1.6 by joko, Fri Apr 4 21:23:29 2003 UTC
# Line 14  Line 14 
14  ##    $Id$  ##    $Id$
15  ##    --------------------------------------------------------------------------  ##    --------------------------------------------------------------------------
16  ##    $Log$  ##    $Log$
17    ##    Revision 1.6  2003/04/04 21:23:29  joko
18    ##    session-based rpc-communcation: revamped code (especially 'function _call')
19    ##    renamed state-handling trigger-methods: now _sleep and _wakeup
20    ##
21    ##    Revision 1.5  2003/03/28 06:56:52  joko
22    ##    updated logging/debugging code
23    ##
24    ##    Revision 1.4  2003/03/28 03:00:12  joko
25    ##    enhanced error- and exception-handling
26    ##
27  ##    Revision 1.3  2003/03/27 16:05:01  joko  ##    Revision 1.3  2003/03/27 16:05:01  joko
28  ##    enhanced 'function _call': debugging, tracing and autodisconnect now parametrized  ##    enhanced 'function _call': debugging, tracing and autodisconnect now parametrized
29  ##  ##
# Line 95  loadModule('Class::Logger'); Line 105  loadModule('Class::Logger');
105  class DataSource_Proxy_XMLRPC extends Class_Logger {  class DataSource_Proxy_XMLRPC extends Class_Logger {
106    
107    var $configured;    var $configured;
108    var $meta;    var $meta = array();
109      var $response = null;
110      var $errors = array();
111        
112    function DataSource_Proxy_XMLRPC($args = array()) {    function DataSource_Proxy_XMLRPC($args = array()) {
113    
114      parent::constructor();      parent::constructor();
115    
116      //print Dumper($this, $args);      //print Dumper($this, $args);
117        //print Dumper($args);
118    
119      global $Data_Driver_RPC_Remote_meta;      $this->_wakeup();
     session_register_safe("Data_Driver_RPC_Remote_meta");  
     $this->meta = $Data_Driver_RPC_Remote_meta;  
120    
121        // force connect?
122        
123        // V1
124        /*
125      if (!isset($this->meta[connected]) || $args[connect]) {      if (!isset($this->meta[connected]) || $args[connect]) {
126        $this->meta[connected] = 1;        $this->meta[connected] = 1;
127      }      }
128      $this->_save_meta();      */
129    
130        // V2
131        $this->FORCE_CONNECT = $args[connect];
132    
133    
134    
135      // merge args - V1      // merge args - V1
136      //if ($args['Host']) { $this->HOST = $args['Host']; }      //if ($args['Host']) { $this->HOST = $args['Host']; }
# Line 122  class DataSource_Proxy_XMLRPC extends Cl Line 142  class DataSource_Proxy_XMLRPC extends Cl
142      //print Dumper($args);      //print Dumper($args);
143      if (is_array($args)) {      if (is_array($args)) {
144        foreach ($args as $key => $val) {        foreach ($args as $key => $val) {
145            //print "key: $key<br/>";
146          $key = strtoupper($key);          $key = strtoupper($key);
147          $this->$key = $val;          $this->$key = $val;
148        }        }
# Line 142  class DataSource_Proxy_XMLRPC extends Cl Line 163  class DataSource_Proxy_XMLRPC extends Cl
163            
164    }    }
165    
166    function _save_meta() {    function _wakeup() {
167        global $Data_Driver_RPC_Remote_meta;
168        session_register_safe("Data_Driver_RPC_Remote_meta");
169        $this->meta = $Data_Driver_RPC_Remote_meta;
170        $this->_sleep();
171      }
172      
173      function _sleep() {
174      global $Data_Driver_RPC_Remote_meta;      global $Data_Driver_RPC_Remote_meta;
175      $Data_Driver_RPC_Remote_meta = $this->meta;      $Data_Driver_RPC_Remote_meta = $this->meta;
176    }    }
# Line 151  class DataSource_Proxy_XMLRPC extends Cl Line 179  class DataSource_Proxy_XMLRPC extends Cl
179    
180      $this->log(get_class($this) . "->send: " . $command, PEAR_LOG_DEBUG);      $this->log(get_class($this) . "->send: " . $command, PEAR_LOG_DEBUG);
181            
182        /*
183      if (!$this->isConnected()) {      if (!$this->isConnected()) {
184        $this->_raiseException( "->send[ command=$command ]: not connected while trying to send command!");        $this->_raiseException( "->send[ command=$command ]: not connected while trying to send command!");
185        return;        return;
186      }      }
187        */
188            
189      // do 'encode' here and ...      // do 'encode' here and ...
190      if ($options[utf8]) {      if ($options[utf8]) {
# Line 168  class DataSource_Proxy_XMLRPC extends Cl Line 198  class DataSource_Proxy_XMLRPC extends Cl
198    
199    function _call($command, $data = "", $options = array() ) {    function _call($command, $data = "", $options = array() ) {
200    
201      if (!$this->configured) {      $RETRY_COUNT = 0;
202        $this->_raiseException( "->_call: class not configured properly");      $RETRY_MAX = 1;
       return;  
     }  
       
     // populate options list - mostly for debugging purposes  
       $options_list = array();  
       foreach ($options as $key => $value) {  
         array_push($options_list, "$key=$value");  
       }  
   
     $data_debug = $data;  
     if (is_array($data_debug)) { $data_debug = join(", ", $data_debug); }  
     $options_debug = join(", ", $options_list);  
     $this->log(get_class($this) . ": " . $command . "(" . $data_debug . ") [" . $options_debug . "]", PEAR_LOG_DEBUG);  
   
     // trace  
       //print "call: $command<hr>";  
       //print Dumper($data);  
       //print Dumper($this);  
203    
204      // data      do {
     $data_enc = XML_RPC_encode($data);  
205    
206      // message - request        $RETRY_COUNT++;
     $msg = new XML_RPC_Message($command);  
     $msg->addParam($data_enc);  
   
     // ???  
     //print htmlentities($msg->serialize());  
   
     // remote procedure call  
     $rpc = new XML_RPC_Client("/", $this->HOST, $this->PORT);  
       
     // TODO: detect highlevel errors, raise proper exceptions on them (e.g. 'Unknown method', 'Method signature error(s)')  
     // done: now possible to declare tracing at this point in configuration  
     //    Please look inside your {appname}/etc/hosts/{hostname}.php  
     $rpc->setDebug($this->TRACE);  
       
     if ( !$msg_response = $rpc->send($msg) ) {  
       // TODO: redirect this error elsewhere!  
       //print "RPC-error!<br>";  
       $this->_raiseException( "->_call: no response");  
       return;  
     }  
207    
208          $this->__exception_method = '_call';
209      
210          if (!$this->configured) {
211            $this->_raiseException("class not configured properly");
212            return;
213          }
214          
215          // populate options list - mostly for debugging purposes
216            $options_list = array();
217            foreach ($options as $key => $value) {
218              array_push($options_list, "$key=$value");
219            }
220      
221          $data_debug = $data;
222          if (is_array($data_debug)) { $data_debug = join(", ", $data_debug); }
223          $options_debug = join(", ", $options_list);
224          // FIXME: replace through '_raiseException'?
225          $this->log(get_class($this) . "->_call: " . $command . "(" . $data_debug . ") [" . $options_debug . "]", PEAR_LOG_DEBUG);
226      
227          // trace
228            //print "call: $command<hr>";
229            //print Dumper($data);
230            //print Dumper($this);
231      
232          // message - request
233          $msg = new XML_RPC_Message($command);
234      
235          // data
236          if ($data) {
237            $data_enc = XML_RPC_encode($data);
238            $msg->addParam($data_enc);
239          }
240      
241          $this->_hook_request($msg);
242      
243          // ???
244          //print htmlentities($msg->serialize());
245      
246          // remote procedure call
247          $rpc = new XML_RPC_Client("/", $this->HOST, $this->PORT);
248          
249          // TODO: detect highlevel errors, raise proper exceptions on them (e.g. 'Unknown method', 'Method signature error(s)')
250          // done: now possible to declare tracing at this point in configuration
251          //    Please look inside your {appname}/etc/hosts/{hostname}.php
252          $rpc->setDebug($this->TRACE);
253          
254          //$rpc->setDebug(1);
255          
256          if ( $this->response = $rpc->send($msg) ) {
257            // intermediate response checking
258            $errcode = $this->_hook_errorcheck();
259            $negotiation = $this->_hook_negotiation($errcode);
260          } else {
261            // TODO: redirect this error elsewhere!
262            //print "RPC-error!<br>";
263            $this->_raiseException("no response");
264            return;
265          }
266      
267          // retry method issued right now - i.e. in case an authentication came in between
268          if (!$negotiation[retry]) {
269            break;
270          }
271          
272        } while ($RETRY_COUNT < $RETRY_MAX);
273        
274      // message - response      // message - response
275      $response_enc = $msg_response->value();      $response_enc = $this->response->value();
   
     // error handling  
     //    Please look inside your {appname}/etc/hosts/{hostname}.php for toggling $this->DEBUG  
     if ($this->DEBUG && $error_code = $msg_response->faultCode()) {  
       //print $msg_response->faultString();  
       $this->_raiseException( "->_call: " . $msg_response->faultString() );  
     }  
276    
277      // TODO: what's this? prematurely returning here should not be considered "stable"....      // TODO: what's this? prematurely returning here should not be considered "stable"....
278      return $this->decodeData($response_enc, $options);      $data = $this->decodeData($response_enc, $options);
279        $this->_hook_response($data);
280        return $data;
281    
282    }    }
283        
# Line 243  class DataSource_Proxy_XMLRPC extends Cl Line 295  class DataSource_Proxy_XMLRPC extends Cl
295            $encoder->toISO();            $encoder->toISO();
296          //}          //}
297                    
298          $this->meta[connected] = 1;          $this->_be_connected();
299          $this->_save_meta();          
   
300          return $data;          return $data;
301        } else {        } else {
302          //print "ERROR!<br>";          //print "ERROR!<br>";
# Line 253  class DataSource_Proxy_XMLRPC extends Cl Line 304  class DataSource_Proxy_XMLRPC extends Cl
304        }        }
305    }    }
306        
307    function _raiseException($message) {    function _be_connected() {
308        $this->meta[connected] = 1;
309        $this->_sleep();
310      }
311      
312      function _raiseException($message, $code = null) {
313        
314        $classname = get_class($this);
315        
316        if ($this->__exception_method) {
317          $message_full = $classname . '->' . $this->__exception_method . ': ' . $message;
318        }
319        
320        // aggregate errors for this run/query
321        $this->_add_error($message, $code);
322            
323      // spout out the error message of the raised exception      // spout out the error message of the raised exception
324      $this->log(get_class($this) . $message, PEAR_LOG_ERR);      $this->log($classname . $message_full, PEAR_LOG_ERR);
325    
326      // handle some stuff regarding more special behaviour (will this get a 'rule' sometimes?)      // handle some stuff regarding more special behaviour (will this get rule-based sometimes?)
327      if ($this->isConnected() && $this->DISCONNECT_ON_ERROR) {      
328        // handle 'FORCE_CONNECT'
329        $connect_condition = $this->FORCE_CONNECT = ($this->isConnected() && $this->DISCONNECT_ON_ERROR);
330        if ($connect_condition) {
331        $message = '->_raiseException: [DISCONNECT_ON_ERROR] done transparently. Please reconnect manually.';        $message = '->_raiseException: [DISCONNECT_ON_ERROR] done transparently. Please reconnect manually.';
332        $this->log(get_class($this) . $message, PEAR_LOG_WARNING);        $this->_add_error($classname . $message, $code);
333          //$this->log($classname . $message, PEAR_LOG_WARNING);
334          $this->log($classname . $message, PEAR_LOG_ERR);
335        $this->meta[connected] = 0;        $this->meta[connected] = 0;
336        $this->_save_meta();        $this->_sleep();
337      }      }
338    }    }
339        
# Line 274  class DataSource_Proxy_XMLRPC extends Cl Line 344  class DataSource_Proxy_XMLRPC extends Cl
344    function ping() {    function ping() {
345      $this->_call('ping');      $this->_call('ping');
346    }    }
347    
348    
349      function _hook_negotiation($error_code) {
350        
351        $result = array();
352        
353        // 401 = authorization required
354        if ($error_code == 401) {
355    
356          //print "<b>401</b>!!!<br/>";
357          //print Dumper($this);
358    
359          // V1 - authenticate using hardcoded plaintext values (bad thing inside here!!!)
360          $auth_ok = $this->_call('authenticate', array( user => 'hello', pass => '123' ));
361          //$auth_ok = $this->_call('authenticate', array( user => 'hello', pass => '12345' ));
362    
363          // authentication success? try issued method again now...
364          if ($auth_ok) {
365            $result[retry] = 1;
366          }
367    
368          // V2 - sub-negotiation:
369          // "Do we already have a password supplied in cache?"
370          // Use it if we have, otherwise redirect to login page
371          // prompting for credentials for specified transport.
372          //Header("Location: " . topicLink('Login'));
373          //print "user: " . $this->USER . "<br/>";
374          //print "pass: " . $this->PASS . "<br/>";
375    
376        }
377    
378        // 511 = sent unknown session identifier (probably: session timed out)
379        // solution: invalidate local session in state => new session will be attempted on next request
380        if ($error_code == 511) {
381          $this->meta[session][enabled] = 0;
382          $this->_sleep();
383        }
384        
385        return $result;
386    
387      }
388    
389      function _hook_errorcheck() {
390        //    Please look inside your {appname}/etc/hosts/{hostname}.php for toggling $this->DEBUG
391        if ($error_code = $this->response->faultCode()) {
392          // raise exception
393          //print "fault-code: " . $this->response->faultCode() . "<br/>";
394          //print "fault-string: " . $this->response->faultString() . "<br/>";
395          $this->_raiseException($this->response->faultString(), $error_code);
396          return $error_code;
397        }
398      }
399    
400      //if ($this->DEBUG && $error_code = $msg_response->faultCode()) {
401    
402      function _add_error($message, $code) {
403        array_push( $this->errors, array(code => $code, message => $message) );
404      }
405      
406      function status() {
407        $status = array(
408          connected => $this->isConnected(),
409          errors => $this->errors,
410        );
411        $status[RPCSESSID] = $this->meta[session][id];
412        return $status;
413      }
414    
415        
416      // TODO: introduce condition: just do if connection requires session/auth
417      function _hook_request(&$request) {
418        
419        //print Dumper($request);
420        
421        // ignore core methods (like 'session_id') here to prevent recursive loops!
422        // would be a bad thing on the net!
423        if (in_array($request->methodname, array('ping', 'session_id')))  { return 1; }
424        
425        // calculate conditions
426        $session_requested = 1;
427        //$use_session = $this->meta[session][requested];
428        $session_running = $this->meta[session][enabled];
429        $session_error = $this->meta[session][error];
430        $init_session = $session_requested && !$session_running && !$session_error;
431        
432        // 1. if session already established, add sessionid to request and return
433        if ($session_running) {
434          //trace("Session " . $this->meta[session][id] . " already initialized!" . "<br/>");
435          // append additional parameter (hash with key 'RPCSESSID')
436          // to send assigned sessionid back to server inside each request
437          $data = array( RPCSESSID => $this->meta[session][id] );
438          $data_enc = XML_RPC_encode($data);
439          //print Dumper($data_enc);
440          $request->addParam($data_enc);
441          //return 1;
442        }
443    
444    
445        // 2. if session is required/requested, but not yet initialized,
446        // do it to be able to propagate the sessionid transparently later
447    
448        if ($init_session) {
449          static $init_count;
450          $init_count++;
451          //trace("Initializing session: $init_count" . "<br/>");
452          //exit;
453          $response = $this->_call('session_id');
454          //print "response: " . Dumper($response) . "<br/>";
455          //exit;
456          
457          if ($response) {
458            $this->meta[session][id] = $response;
459            $this->meta[session][enabled] = 1;
460          } else {
461            $this->meta[session][error] = 1;
462          }
463          
464          $this->_sleep();
465          //print Dumper($this->meta);
466          //exit;
467        }
468    
469        //print Dumper($request);
470    
471        return 1;
472      }
473    
474      function _hook_response(&$data) {
475        //$status[RPCSESSID] = $this->meta[session][RPCSESSID];
476      }
477    
478  }  }
479    
480  ?>  ?>

Legend:
Removed from v.1.3  
changed lines
  Added in v.1.6

MailToCvsAdmin">MailToCvsAdmin
ViewVC Help
Powered by ViewVC 1.1.26 RSS 2.0 feed