lib: fixed virtual destructor in Connector base class
[barry.git] / src / connector.cc
blobfabe2c4dceac2394477f127678874ff9b6c44521
1 //
2 // \file connector.cc
3 // Base class interface for handling Mode connections to device
4 //
6 /*
7 Copyright (C) 2011, Net Direct Inc. (http://www.netdirect.ca/)
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 See the GNU General Public License in the COPYING file at the
19 root directory of this project for more details.
22 #include "connector.h"
23 #include "router.h"
24 #include "controller.h"
25 #include "m_desktop.h"
26 #include "debug.h"
28 using namespace std;
29 using namespace Barry;
31 namespace Barry {
33 //////////////////////////////////////////////////////////////////////////////
34 // Connector base class
36 // we use a const char *password here because we don't want the
37 // responsibility of clear its memory... that's the application's job
38 Connector::Connector(const char *password,
39 const std::string &locale,
40 Barry::Pin pin)
41 : m_password(password)
42 , m_needs_reconnect(false)
43 , m_ic(locale.c_str())
44 , m_probe_result(FindDevice(pin))
45 , m_connect_count(0)
46 , m_last_disconnect(0)
50 Connector::Connector(const char *password,
51 const std::string &locale,
52 const Barry::ProbeResult &result)
53 : m_password(password)
54 , m_needs_reconnect(false)
55 , m_ic(locale.c_str())
56 , m_probe_result(result)
57 , m_connect_count(0)
58 , m_last_disconnect(0)
62 Connector::~Connector()
66 Barry::ProbeResult Connector::FindDevice(Barry::Pin pin)
68 Barry::Probe probe;
69 int i = probe.FindActive(pin);
70 if( i != -1 )
71 return probe.Get(i);
72 else
73 throw Barry::PinNotFound(pin, probe.GetCount());
76 void Connector::ClearPassword()
78 // blank the memory first
79 size_t len = m_password.size();
80 while( len ) {
81 len--;
82 m_password[len] = '0';
85 // free it
86 m_password.clear();
89 void Connector::SetPassword(const char *password)
91 ClearPassword();
92 m_password = password;
95 bool Connector::Connect()
97 Disconnect();
99 bool started = false;
100 BadPassword bpcopy("", 0, 0);
101 for(;;) {
103 try {
104 if( !started ) {
105 started = true;
106 StartConnect(m_password.c_str());
108 else {
109 RetryPassword(m_password.c_str());
112 FinishConnect();
113 m_connect_count++;
114 return true;
117 catch( BadPassword &bp ) {
118 if( bp.out_of_tries() ) {
119 throw;
122 bpcopy = bp;
124 // fall through to password prompt
127 // ask user for device password
128 ClearPassword();
129 if( !PasswordPrompt(bpcopy, m_password) ) {
130 // user wants out
131 return false;
136 void Connector::Disconnect()
138 m_needs_reconnect = false;
139 if( !IsDisconnected() ) {
140 DoDisconnect();
141 m_last_disconnect = time(NULL);
145 bool Connector::Reconnect(int total_tries)
147 int tries = 0;
149 while(1) try {
151 tries++;
153 Disconnect();
155 if( m_connect_count ) {
156 // let the device settle... this seems to help prevent
157 // the firmware hang, and therefore ultimately speeds
158 // up the sync
159 if( (time(NULL) - m_last_disconnect) < 2 ) {
160 // don't bother sleeping if 2 seconds have
161 // already passed
162 sleep(1);
165 // temporary fix for odd reconnect message...
166 // without this probe, the reconnect will often fail on
167 // newer Blackberries due to an unexpected close socket
168 // message.
170 // It is unclear if this is really a message from
171 // the device, but until then, we add this probe.
172 m_probe_result = FindDevice(m_probe_result.m_pin);
175 return Connect();
177 catch( Usb::Timeout & ) {
178 if( tries >= total_tries ) {
179 throw;
181 else {
182 dout("Timeout in Connector::Reconnect()... trying again");
187 bool Connector::ReconnectForDirtyFlags()
189 if( m_needs_reconnect ) {
190 return Reconnect();
192 else {
193 return true;
197 void Connector::RequireDirtyReconnect()
199 m_needs_reconnect = true;
203 //////////////////////////////////////////////////////////////////////////////
204 // DesktopConnector class
206 DesktopConnector::DesktopConnector(const char *password,
207 const std::string &locale,
208 Barry::Pin pin,
209 Barry::SocketRoutingQueue *router,
210 int connect_timeout)
211 : Connector(password, locale, pin)
212 , m_router(router)
213 , m_connect_timeout(connect_timeout)
217 DesktopConnector::DesktopConnector(const char *password,
218 const std::string &locale,
219 const Barry::ProbeResult &result,
220 Barry::SocketRoutingQueue *router,
221 int connect_timeout)
222 : Connector(password, locale, result)
223 , m_router(router)
224 , m_connect_timeout(connect_timeout)
228 void DesktopConnector::StartConnect(const char *password)
230 // Note that there is a firmware issue that causes the firmware
231 // to sometimes hang during a connect and it fails to respond
232 // to a Desktop::Open() call. To work around this, set the
233 // timeout to something lower than the usual 30 seconds.
234 // The default in DesktopConnector is 10 seconds, which should
235 // be fine.
237 // If this bug triggers, a Timeout exception will be thrown,
238 // which will be caught by the Reconnect() method, and Reconnect()
239 // will retry according to the total number of retries it is
240 // set to do.
242 if( m_router ) {
243 m_con.reset( new Barry::Controller(m_probe_result,
244 *m_router, m_connect_timeout) );
246 else {
247 m_con.reset( new Barry::Controller(m_probe_result,
248 m_connect_timeout) );
250 m_desktop.reset( new Barry::Mode::Desktop(*m_con, m_ic) );
251 m_desktop->Open(password);
254 void DesktopConnector::RetryPassword(const char *password)
256 m_desktop->RetryPassword(password);
259 void DesktopConnector::FinishConnect()
263 void DesktopConnector::DoDisconnect()
265 m_desktop.reset();
266 m_con.reset();
269 bool DesktopConnector::IsDisconnected()
271 // return true if DoDisconnect can safely be skipped
272 return !m_con.get() && !m_desktop.get();
275 bool DesktopConnector::IsConnected()
277 if( m_con.get() && m_desktop.get() )
278 return true;
279 return false;