connector.cc

00001 //
00002 // \file        connector.cc
00003 //              Base class interface for handling Mode connections to device
00004 //
00005 
00006 /*
00007     Copyright (C) 2011, Net Direct Inc. (http://www.netdirect.ca/)
00008 
00009     This program is free software; you can redistribute it and/or modify
00010     it under the terms of the GNU General Public License as published by
00011     the Free Software Foundation; either version 2 of the License, or
00012     (at your option) any later version.
00013 
00014     This program is distributed in the hope that it will be useful,
00015     but WITHOUT ANY WARRANTY; without even the implied warranty of
00016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00017 
00018     See the GNU General Public License in the COPYING file at the
00019     root directory of this project for more details.
00020 */
00021 
00022 #include "connector.h"
00023 #include "router.h"
00024 #include "controller.h"
00025 #include "m_desktop.h"
00026 #include "debug.h"
00027 
00028 using namespace std;
00029 using namespace Barry;
00030 
00031 namespace Barry {
00032 
00033 //////////////////////////////////////////////////////////////////////////////
00034 // Connector base class
00035 
00036 // we use a const char *password here because we don't want the
00037 // responsibility of clear its memory... that's the application's job
00038 Connector::Connector(const char *password,
00039                      const std::string &locale,
00040                      Barry::Pin pin)
00041         : m_password(password)
00042         , m_needs_reconnect(false)
00043         , m_ic(locale.c_str())
00044         , m_probe_result(FindDevice(pin))
00045         , m_connect_count(0)
00046         , m_last_disconnect(0)
00047 {
00048 }
00049 
00050 Connector::Connector(const char *password,
00051                      const std::string &locale,
00052                      const Barry::ProbeResult &result)
00053         : m_password(password)
00054         , m_needs_reconnect(false)
00055         , m_ic(locale.c_str())
00056         , m_probe_result(result)
00057         , m_connect_count(0)
00058         , m_last_disconnect(0)
00059 {
00060 }
00061 
00062 Connector::~Connector()
00063 {
00064 }
00065 
00066 Barry::ProbeResult Connector::FindDevice(Barry::Pin pin)
00067 {
00068         Barry::Probe probe;
00069         int i = probe.FindActive(pin);
00070         if( i != -1 )
00071                 return probe.Get(i);
00072         else
00073                 throw Barry::PinNotFound(pin, probe.GetCount());
00074 }
00075 
00076 void Connector::ClearPassword()
00077 {
00078         // blank the memory first
00079         size_t len = m_password.size();
00080         while( len ) {
00081                 len--;
00082                 m_password[len] = '0';
00083         }
00084 
00085         // free it
00086         m_password.clear();
00087 }
00088 
00089 void Connector::SetPassword(const char *password)
00090 {
00091         ClearPassword();
00092         m_password = password;
00093 }
00094 
00095 bool Connector::Connect()
00096 {
00097         Disconnect();
00098 
00099         bool started = false;
00100         BadPassword bpcopy("", 0, 0);
00101         for(;;) {
00102 
00103                 try {
00104                         if( !started ) {
00105                                 started = true;
00106                                 StartConnect(m_password.c_str());
00107                         }
00108                         else {
00109                                 RetryPassword(m_password.c_str());
00110                         }
00111 
00112                         FinishConnect();
00113                         m_connect_count++;
00114                         return true;
00115 
00116                 }
00117                 catch( BadPassword &bp ) {
00118                         if( bp.out_of_tries() ) {
00119                                 throw;
00120                         }
00121 
00122                         bpcopy = bp;
00123 
00124                         // fall through to password prompt
00125                 }
00126 
00127                 // ask user for device password
00128                 ClearPassword();
00129                 if( !PasswordPrompt(bpcopy, m_password) ) {
00130                         // user wants out
00131                         return false;
00132                 }
00133         }
00134 }
00135 
00136 void Connector::Disconnect()
00137 {
00138         m_needs_reconnect = false;
00139         if( !IsDisconnected() ) {
00140                 DoDisconnect();
00141                 m_last_disconnect = time(NULL);
00142         }
00143 }
00144 
00145 bool Connector::Reconnect(int total_tries)
00146 {
00147         int tries = 0;
00148 
00149         while(1) try {
00150 
00151                 tries++;
00152 
00153                 Disconnect();
00154 
00155                 if( m_connect_count ) {
00156                         // let the device settle... this seems to help prevent
00157                         // the firmware hang, and therefore ultimately speeds
00158                         // up the sync
00159                         if( (time(NULL) - m_last_disconnect) < 2 ) {
00160                                 // don't bother sleeping if 2 seconds have
00161                                 // already passed
00162                                 sleep(1);
00163                         }
00164 
00165                         // temporary fix for odd reconnect message...
00166                         // without this probe, the reconnect will often fail on
00167                         // newer Blackberries due to an unexpected close socket
00168                         // message.
00169                         //
00170                         // It is unclear if this is really a message from
00171                         // the device, but until then, we add this probe.
00172                         m_probe_result = FindDevice(m_probe_result.m_pin);
00173                 }
00174 
00175                 return Connect();
00176         }
00177         catch( Usb::Timeout & ) {
00178                 if( tries >= total_tries ) {
00179                         throw;
00180                 }
00181                 else {
00182                         dout("Timeout in Connector::Reconnect()... trying again");
00183                 }
00184         }
00185 }
00186 
00187 bool Connector::ReconnectForDirtyFlags()
00188 {
00189         if( m_needs_reconnect ) {
00190                 return Reconnect();
00191         }
00192         else {
00193                 return true;
00194         }
00195 }
00196 
00197 void Connector::RequireDirtyReconnect()
00198 {
00199         m_needs_reconnect = true;
00200 }
00201 
00202 
00203 //////////////////////////////////////////////////////////////////////////////
00204 // DesktopConnector class
00205 
00206 DesktopConnector::DesktopConnector(const char *password,
00207                                 const std::string &locale,
00208                                 Barry::Pin pin,
00209                                 Barry::SocketRoutingQueue *router,
00210                                 int connect_timeout)
00211         : Connector(password, locale, pin)
00212         , m_router(router)
00213         , m_connect_timeout(connect_timeout)
00214 {
00215 }
00216 
00217 DesktopConnector::DesktopConnector(const char *password,
00218                                 const std::string &locale,
00219                                 const Barry::ProbeResult &result,
00220                                 Barry::SocketRoutingQueue *router,
00221                                 int connect_timeout)
00222         : Connector(password, locale, result)
00223         , m_router(router)
00224         , m_connect_timeout(connect_timeout)
00225 {
00226 }
00227 
00228 void DesktopConnector::StartConnect(const char *password)
00229 {
00230         // Note that there is a firmware issue that causes the firmware
00231         // to sometimes hang during a connect and it fails to respond
00232         // to a Desktop::Open() call.  To work around this, set the
00233         // timeout to something lower than the usual 30 seconds.
00234         // The default in DesktopConnector is 10 seconds, which should
00235         // be fine.
00236         //
00237         // If this bug triggers, a Timeout exception will be thrown,
00238         // which will be caught by the Reconnect() method, and Reconnect()
00239         // will retry according to the total number of retries it is
00240         // set to do.
00241         //
00242         if( m_router ) {
00243                 m_con.reset( new Barry::Controller(m_probe_result,
00244                                                 *m_router, m_connect_timeout) );
00245         }
00246         else {
00247                 m_con.reset( new Barry::Controller(m_probe_result,
00248                                                 m_connect_timeout) );
00249         }
00250         m_desktop.reset( new Barry::Mode::Desktop(*m_con, m_ic) );
00251         m_desktop->Open(password);
00252 }
00253 
00254 void DesktopConnector::RetryPassword(const char *password)
00255 {
00256         m_desktop->RetryPassword(password);
00257 }
00258 
00259 void DesktopConnector::FinishConnect()
00260 {
00261 }
00262 
00263 void DesktopConnector::DoDisconnect()
00264 {
00265         m_desktop.reset();
00266         m_con.reset();
00267 }
00268 
00269 bool DesktopConnector::IsDisconnected()
00270 {
00271         // return true if DoDisconnect can safely be skipped
00272         return !m_con.get() && !m_desktop.get();
00273 }
00274 
00275 bool DesktopConnector::IsConnected()
00276 {
00277         if( m_con.get() && m_desktop.get() )
00278                 return true;
00279         return false;
00280 }
00281 
00282 }
00283 

Generated on Tue Mar 1 17:50:15 2011 for Barry by  doxygen 1.5.6