menu: added new Keywords tag to .desktop files
[barry.git] / src / connector.cc
bloba5c3ff292c3d0c538d7fcc5f5febfea040b07264
1 ///
2 /// \file connector.cc
3 /// Base class interface for handling Mode connections to device
4 ///
6 /*
7 Copyright (C) 2011-2013, 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 "i18n.h"
23 #include "connector.h"
24 #include "router.h"
25 #include "controller.h"
26 #include "m_desktop.h"
27 #include "debug.h"
28 #include <unistd.h>
30 using namespace std;
31 using namespace Barry;
33 namespace Barry {
35 //////////////////////////////////////////////////////////////////////////////
36 // Connector base class
38 // we use a const char *password here because we don't want the
39 // responsibility of clear its memory... that's the application's job
40 Connector::Connector(const char *password,
41 const std::string &locale,
42 Barry::Pin pin)
43 : m_password(password)
44 , m_needs_reconnect(false)
45 , m_ic(locale.c_str())
46 , m_probe_result(FindDevice(pin))
47 , m_connect_count(0)
48 , m_last_disconnect(0)
49 , m_bpcopy("", 0, 0)
53 Connector::Connector(const char *password,
54 const std::string &locale,
55 const Barry::ProbeResult &result)
56 : m_password(password)
57 , m_needs_reconnect(false)
58 , m_ic(locale.c_str())
59 , m_probe_result(result)
60 , m_connect_count(0)
61 , m_last_disconnect(0)
62 , m_bpcopy("", 0, 0)
66 Connector::~Connector()
70 Barry::ProbeResult Connector::FindDevice(Barry::Pin pin)
72 Barry::Probe probe;
73 int i = probe.FindActive(pin);
74 if( i != -1 )
75 return probe.Get(i);
76 else
77 throw Barry::PinNotFound(pin, probe.GetCount());
80 void Connector::ClearPassword()
82 // blank the memory first
83 size_t len = m_password.size();
84 while( len ) {
85 len--;
86 m_password[len] = '0';
89 // free it
90 m_password.clear();
93 void Connector::SetPassword(const char *password)
95 ClearPassword();
96 m_password = password;
99 bool Connector::Connect()
101 Disconnect();
103 bool started = false;
104 for(;;) {
106 try {
107 if( !started ) {
108 started = true;
109 StartConnect(m_password.c_str());
111 else {
112 RetryPassword(m_password.c_str());
115 FinishConnect();
116 m_connect_count++;
117 return true;
120 catch( BadPassword &bp ) {
121 if( bp.out_of_tries() ) {
122 throw;
125 m_bpcopy = bp;
127 // fall through to password prompt
130 // ask user for device password
131 ClearPassword();
132 if( !PasswordPrompt(m_bpcopy, m_password) ) {
133 // user wants out
134 return false;
139 void Connector::Disconnect()
141 m_needs_reconnect = false;
142 if( !IsDisconnected() ) {
143 DoDisconnect();
144 m_last_disconnect = time(NULL);
148 bool Connector::Reconnect(int total_tries)
150 int tries = 0;
152 while(1) try {
154 tries++;
156 Disconnect();
158 if( m_connect_count ) {
159 // let the device settle... this seems to help prevent
160 // the firmware hang, and therefore ultimately speeds
161 // up the sync
162 if( (time(NULL) - m_last_disconnect) < 2 ) {
163 // don't bother sleeping if 2 seconds have
164 // already passed
165 sleep(1);
168 // temporary fix for odd reconnect message...
169 // without this probe, the reconnect will often fail on
170 // newer Blackberries due to an unexpected close socket
171 // message.
173 // It is unclear if this is really a message from
174 // the device, but until then, we add this probe.
175 m_probe_result = FindDevice(m_probe_result.m_pin);
178 return Connect();
180 catch( Usb::Timeout & ) {
181 if( tries >= total_tries ) {
182 throw;
184 else {
185 dout(_("Timeout in Connector::Reconnect()... trying again"));
190 bool Connector::ReconnectForDirtyFlags()
192 if( m_needs_reconnect ) {
193 return Reconnect();
195 else {
196 return true;
200 void Connector::RequireDirtyReconnect()
202 m_needs_reconnect = true;
206 //////////////////////////////////////////////////////////////////////////////
207 // DesktopConnector class
209 DesktopConnector::DesktopConnector(const char *password,
210 const std::string &locale,
211 Barry::Pin pin,
212 Barry::SocketRoutingQueue *router,
213 int connect_timeout)
214 : Connector(password, locale, pin)
215 , m_router(router)
216 , m_connect_timeout(connect_timeout)
220 DesktopConnector::DesktopConnector(const char *password,
221 const std::string &locale,
222 const Barry::ProbeResult &result,
223 Barry::SocketRoutingQueue *router,
224 int connect_timeout)
225 : Connector(password, locale, result)
226 , m_router(router)
227 , m_connect_timeout(connect_timeout)
231 void DesktopConnector::StartConnect(const char *password)
233 // Note that there is a firmware issue that causes the firmware
234 // to sometimes hang during a connect and it fails to respond
235 // to a Desktop::Open() call. To work around this, set the
236 // timeout to something lower than the usual 30 seconds.
237 // The default in DesktopConnector is 10 seconds, which should
238 // be fine.
240 // If this bug triggers, a Timeout exception will be thrown,
241 // which will be caught by the Reconnect() method, and Reconnect()
242 // will retry according to the total number of retries it is
243 // set to do.
245 if( m_router ) {
246 m_con.reset( new Barry::Controller(m_probe_result,
247 *m_router, m_connect_timeout) );
249 else {
250 m_con.reset( new Barry::Controller(m_probe_result,
251 m_connect_timeout) );
253 m_desktop.reset( new Barry::Mode::Desktop(*m_con, m_ic) );
254 m_desktop->Open(password);
257 void DesktopConnector::RetryPassword(const char *password)
259 m_desktop->RetryPassword(password);
262 void DesktopConnector::FinishConnect()
266 void DesktopConnector::DoDisconnect()
268 m_desktop.reset();
269 m_con.reset();
272 bool DesktopConnector::IsDisconnected()
274 // return true if DoDisconnect can safely be skipped
275 return !m_con.get() && !m_desktop.get();
278 bool DesktopConnector::IsConnected()
280 if( m_con.get() && m_desktop.get() )
281 return true;
282 return false;