desktop: added pin display to the ModemDlg
[barry.git] / src / connector.cc
blobd9d40a33cf9f611654fb44b03ede689783d8fd33
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"
27 #include <unistd.h>
29 using namespace std;
30 using namespace Barry;
32 namespace Barry {
34 //////////////////////////////////////////////////////////////////////////////
35 // Connector base class
37 // we use a const char *password here because we don't want the
38 // responsibility of clear its memory... that's the application's job
39 Connector::Connector(const char *password,
40 const std::string &locale,
41 Barry::Pin pin)
42 : m_password(password)
43 , m_needs_reconnect(false)
44 , m_ic(locale.c_str())
45 , m_probe_result(FindDevice(pin))
46 , m_connect_count(0)
47 , m_last_disconnect(0)
48 , m_bpcopy("", 0, 0)
52 Connector::Connector(const char *password,
53 const std::string &locale,
54 const Barry::ProbeResult &result)
55 : m_password(password)
56 , m_needs_reconnect(false)
57 , m_ic(locale.c_str())
58 , m_probe_result(result)
59 , m_connect_count(0)
60 , m_last_disconnect(0)
61 , m_bpcopy("", 0, 0)
65 Connector::~Connector()
69 Barry::ProbeResult Connector::FindDevice(Barry::Pin pin)
71 Barry::Probe probe;
72 int i = probe.FindActive(pin);
73 if( i != -1 )
74 return probe.Get(i);
75 else
76 throw Barry::PinNotFound(pin, probe.GetCount());
79 void Connector::ClearPassword()
81 // blank the memory first
82 size_t len = m_password.size();
83 while( len ) {
84 len--;
85 m_password[len] = '0';
88 // free it
89 m_password.clear();
92 void Connector::SetPassword(const char *password)
94 ClearPassword();
95 m_password = password;
98 bool Connector::Connect()
100 Disconnect();
102 bool started = false;
103 for(;;) {
105 try {
106 if( !started ) {
107 started = true;
108 StartConnect(m_password.c_str());
110 else {
111 RetryPassword(m_password.c_str());
114 FinishConnect();
115 m_connect_count++;
116 return true;
119 catch( BadPassword &bp ) {
120 if( bp.out_of_tries() ) {
121 throw;
124 m_bpcopy = bp;
126 // fall through to password prompt
129 // ask user for device password
130 ClearPassword();
131 if( !PasswordPrompt(m_bpcopy, m_password) ) {
132 // user wants out
133 return false;
138 void Connector::Disconnect()
140 m_needs_reconnect = false;
141 if( !IsDisconnected() ) {
142 DoDisconnect();
143 m_last_disconnect = time(NULL);
147 bool Connector::Reconnect(int total_tries)
149 int tries = 0;
151 while(1) try {
153 tries++;
155 Disconnect();
157 if( m_connect_count ) {
158 // let the device settle... this seems to help prevent
159 // the firmware hang, and therefore ultimately speeds
160 // up the sync
161 if( (time(NULL) - m_last_disconnect) < 2 ) {
162 // don't bother sleeping if 2 seconds have
163 // already passed
164 sleep(1);
167 // temporary fix for odd reconnect message...
168 // without this probe, the reconnect will often fail on
169 // newer Blackberries due to an unexpected close socket
170 // message.
172 // It is unclear if this is really a message from
173 // the device, but until then, we add this probe.
174 m_probe_result = FindDevice(m_probe_result.m_pin);
177 return Connect();
179 catch( Usb::Timeout & ) {
180 if( tries >= total_tries ) {
181 throw;
183 else {
184 dout("Timeout in Connector::Reconnect()... trying again");
189 bool Connector::ReconnectForDirtyFlags()
191 if( m_needs_reconnect ) {
192 return Reconnect();
194 else {
195 return true;
199 void Connector::RequireDirtyReconnect()
201 m_needs_reconnect = true;
205 //////////////////////////////////////////////////////////////////////////////
206 // DesktopConnector class
208 DesktopConnector::DesktopConnector(const char *password,
209 const std::string &locale,
210 Barry::Pin pin,
211 Barry::SocketRoutingQueue *router,
212 int connect_timeout)
213 : Connector(password, locale, pin)
214 , m_router(router)
215 , m_connect_timeout(connect_timeout)
219 DesktopConnector::DesktopConnector(const char *password,
220 const std::string &locale,
221 const Barry::ProbeResult &result,
222 Barry::SocketRoutingQueue *router,
223 int connect_timeout)
224 : Connector(password, locale, result)
225 , m_router(router)
226 , m_connect_timeout(connect_timeout)
230 void DesktopConnector::StartConnect(const char *password)
232 // Note that there is a firmware issue that causes the firmware
233 // to sometimes hang during a connect and it fails to respond
234 // to a Desktop::Open() call. To work around this, set the
235 // timeout to something lower than the usual 30 seconds.
236 // The default in DesktopConnector is 10 seconds, which should
237 // be fine.
239 // If this bug triggers, a Timeout exception will be thrown,
240 // which will be caught by the Reconnect() method, and Reconnect()
241 // will retry according to the total number of retries it is
242 // set to do.
244 if( m_router ) {
245 m_con.reset( new Barry::Controller(m_probe_result,
246 *m_router, m_connect_timeout) );
248 else {
249 m_con.reset( new Barry::Controller(m_probe_result,
250 m_connect_timeout) );
252 m_desktop.reset( new Barry::Mode::Desktop(*m_con, m_ic) );
253 m_desktop->Open(password);
256 void DesktopConnector::RetryPassword(const char *password)
258 m_desktop->RetryPassword(password);
261 void DesktopConnector::FinishConnect()
265 void DesktopConnector::DoDisconnect()
267 m_desktop.reset();
268 m_con.reset();
271 bool DesktopConnector::IsDisconnected()
273 // return true if DoDisconnect can safely be skipped
274 return !m_con.get() && !m_desktop.get();
277 bool DesktopConnector::IsConnected()
279 if( m_con.get() && m_desktop.get() )
280 return true;
281 return false;