maint: remove -j2 flags on Fedora/OpenSUSE to workaround Make 3.82 borkage
[barry/progweb.git] / src / connector.cc
blob837ae7b33b6d92b4d07b5a01ece1a89d8a7b8aca
1 ///
2 /// \file connector.cc
3 /// Base class interface for handling Mode connections to device
4 ///
6 /*
7 Copyright (C) 2011-2012, 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)
47 , m_bpcopy("", 0, 0)
51 Connector::Connector(const char *password,
52 const std::string &locale,
53 const Barry::ProbeResult &result)
54 : m_password(password)
55 , m_needs_reconnect(false)
56 , m_ic(locale.c_str())
57 , m_probe_result(result)
58 , m_connect_count(0)
59 , m_last_disconnect(0)
60 , m_bpcopy("", 0, 0)
64 Connector::~Connector()
68 Barry::ProbeResult Connector::FindDevice(Barry::Pin pin)
70 Barry::Probe probe;
71 int i = probe.FindActive(pin);
72 if( i != -1 )
73 return probe.Get(i);
74 else
75 throw Barry::PinNotFound(pin, probe.GetCount());
78 void Connector::ClearPassword()
80 // blank the memory first
81 size_t len = m_password.size();
82 while( len ) {
83 len--;
84 m_password[len] = '0';
87 // free it
88 m_password.clear();
91 void Connector::SetPassword(const char *password)
93 ClearPassword();
94 m_password = password;
97 bool Connector::Connect()
99 Disconnect();
101 bool started = false;
102 for(;;) {
104 try {
105 if( !started ) {
106 started = true;
107 StartConnect(m_password.c_str());
109 else {
110 RetryPassword(m_password.c_str());
113 FinishConnect();
114 m_connect_count++;
115 return true;
118 catch( BadPassword &bp ) {
119 if( bp.out_of_tries() ) {
120 throw;
123 m_bpcopy = bp;
125 // fall through to password prompt
128 // ask user for device password
129 ClearPassword();
130 if( !PasswordPrompt(m_bpcopy, m_password) ) {
131 // user wants out
132 return false;
137 void Connector::Disconnect()
139 m_needs_reconnect = false;
140 if( !IsDisconnected() ) {
141 DoDisconnect();
142 m_last_disconnect = time(NULL);
146 bool Connector::Reconnect(int total_tries)
148 int tries = 0;
150 while(1) try {
152 tries++;
154 Disconnect();
156 if( m_connect_count ) {
157 // let the device settle... this seems to help prevent
158 // the firmware hang, and therefore ultimately speeds
159 // up the sync
160 if( (time(NULL) - m_last_disconnect) < 2 ) {
161 // don't bother sleeping if 2 seconds have
162 // already passed
163 sleep(1);
166 // temporary fix for odd reconnect message...
167 // without this probe, the reconnect will often fail on
168 // newer Blackberries due to an unexpected close socket
169 // message.
171 // It is unclear if this is really a message from
172 // the device, but until then, we add this probe.
173 m_probe_result = FindDevice(m_probe_result.m_pin);
176 return Connect();
178 catch( Usb::Timeout & ) {
179 if( tries >= total_tries ) {
180 throw;
182 else {
183 dout("Timeout in Connector::Reconnect()... trying again");
188 bool Connector::ReconnectForDirtyFlags()
190 if( m_needs_reconnect ) {
191 return Reconnect();
193 else {
194 return true;
198 void Connector::RequireDirtyReconnect()
200 m_needs_reconnect = true;
204 //////////////////////////////////////////////////////////////////////////////
205 // DesktopConnector class
207 DesktopConnector::DesktopConnector(const char *password,
208 const std::string &locale,
209 Barry::Pin pin,
210 Barry::SocketRoutingQueue *router,
211 int connect_timeout)
212 : Connector(password, locale, pin)
213 , m_router(router)
214 , m_connect_timeout(connect_timeout)
218 DesktopConnector::DesktopConnector(const char *password,
219 const std::string &locale,
220 const Barry::ProbeResult &result,
221 Barry::SocketRoutingQueue *router,
222 int connect_timeout)
223 : Connector(password, locale, result)
224 , m_router(router)
225 , m_connect_timeout(connect_timeout)
229 void DesktopConnector::StartConnect(const char *password)
231 // Note that there is a firmware issue that causes the firmware
232 // to sometimes hang during a connect and it fails to respond
233 // to a Desktop::Open() call. To work around this, set the
234 // timeout to something lower than the usual 30 seconds.
235 // The default in DesktopConnector is 10 seconds, which should
236 // be fine.
238 // If this bug triggers, a Timeout exception will be thrown,
239 // which will be caught by the Reconnect() method, and Reconnect()
240 // will retry according to the total number of retries it is
241 // set to do.
243 if( m_router ) {
244 m_con.reset( new Barry::Controller(m_probe_result,
245 *m_router, m_connect_timeout) );
247 else {
248 m_con.reset( new Barry::Controller(m_probe_result,
249 m_connect_timeout) );
251 m_desktop.reset( new Barry::Mode::Desktop(*m_con, m_ic) );
252 m_desktop->Open(password);
255 void DesktopConnector::RetryPassword(const char *password)
257 m_desktop->RetryPassword(password);
260 void DesktopConnector::FinishConnect()
264 void DesktopConnector::DoDisconnect()
266 m_desktop.reset();
267 m_con.reset();
270 bool DesktopConnector::IsDisconnected()
272 // return true if DoDisconnect can safely be skipped
273 return !m_con.get() && !m_desktop.get();
276 bool DesktopConnector::IsConnected()
278 if( m_con.get() && m_desktop.get() )
279 return true;
280 return false;