7 Copyright (C) 2010, RealVNC Ltd.
9 Some parts are inspired from bjavaloader.cc
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20 See the GNU General Public License in the COPYING file at the
21 root directory of this project for more details.
25 #include <barry/barry.h>
34 #include <sys/types.h>
35 #include <sys/socket.h>
36 #include <netinet/in.h>
37 #include <arpa/inet.h>
42 using namespace Barry
;
44 class TCPWriter
: public Barry::Mode::VNCServerDataCallback
47 void SetSocket(int socket
, bool& keepGoing
)
50 continuePtr
= &keepGoing
;
53 void DataReceived(Data
& data
)
55 std::cerr
<< "From BB: ";
56 data
.DumpHex(std::cerr
);
59 size_t toWrite
= data
.GetSize();
62 while (written
< toWrite
)
64 ssize_t writtenThisTime
= write(cfd
, &(data
.GetData()[written
]), toWrite
- written
);
65 if (writtenThisTime
< 0)
71 written
+= writtenThisTime
;
84 const char *Version
= Barry::Version(major
, minor
);
87 << "bvncrelay - Command line USB Blackberry VNC Relay\n"
88 << " Copyright 2010, RealVNC Ltd.\n"
89 << " Using: " << Version
<< "\n"
92 << " -s List sibling in module list\n"
93 << " -p pin PIN of device to talk with\n"
94 << " If only one device is plugged in, this flag is optional\n"
95 << " -P pass Simplistic method to specify device password\n"
96 << " -v Dump protocol data during operation\n"
101 static void handle_error(const char* text
)
103 throw new std::runtime_error(text
);
107 int main(int argc
, char *argv
[])
111 cout
.sync_with_stdio(true); // leave this on, since libusb uses
112 // stdio for debug messages
117 bool list_siblings
= false,
120 vector
<string
> params
;
124 Usb::EndpointPair epOverride
;
126 // process command line options
128 int cmd
= getopt(argc
, argv
, "hsp:P:v");
134 case 'p': // Blackberry PIN
135 pin
= strtoul(optarg
, NULL
, 16);
138 case 'P': // Device password
142 case 's': // turn on listing of sibling modules
143 list_siblings
= true;
146 case 'v': // data dump on
161 cerr
<< "missing command" << endl
;
166 // Fetch command from remaining arguments
167 string cmd
= argv
[0];
171 // Put the remaining arguments into an array
172 for (; argc
> 0; argc
--, argv
++) {
173 params
.push_back(string(argv
[0]));
176 // Initialize the barry library. Must be called before
178 Barry::Init(data_dump
);
180 // Probe the USB bus for Blackberry devices and display.
181 // If user has specified a PIN, search for it in the
182 // available device list here as well
184 int activeDevice
= probe
.FindActive(pin
);
185 if( activeDevice
== -1 ) {
186 cerr
<< "No device selected, or PIN not found" << endl
;
190 // Create the thing which will write onto TCP
193 // Start a thread to handle any data arriving from
195 auto_ptr
<SocketRoutingQueue
> router
;
196 router
.reset(new SocketRoutingQueue
);
197 router
->SpinoffSimpleReadThread();
199 // Create our controller object
200 Barry::Controller
con(probe
.Get(activeDevice
), *router
);
201 Barry::Mode::VNCServer
vncrelay(con
, tcpwriter
);
204 // execute each mode that was turned on
206 vncrelay
.Open(password
.c_str());
208 // Now start to read from TCP and get ready to write
209 // to the BlackBerry.
210 int sfd
= socket(AF_INET
, SOCK_STREAM
, 0);
212 handle_error("socket");
215 memset(&my_addr
, 0, sizeof(struct sockaddr_in
));
216 /* Clear structure */
217 my_addr
.sin_family
= AF_INET
;
218 my_addr
.sin_port
= 2000;
219 my_addr
.sin_addr
.s_addr
= INADDR_ANY
;
221 if (bind(sfd
, (struct sockaddr
*) &my_addr
,
222 sizeof(struct sockaddr_in
)) == -1)
223 handle_error("bind");
225 if (listen(sfd
, 1) == -1)
226 handle_error("listen");
228 /* Now we can accept incoming connections one
229 at a time using accept(2) */
231 sockaddr_in peer_addr
;
232 socklen_t peer_addr_size
= sizeof(struct sockaddr_in
);
233 int cfd
= accept(sfd
, (struct sockaddr
*) &peer_addr
,
236 handle_error("accept");
239 std::cerr
<< "Accepted\n";
242 tcpwriter
.SetSocket(cfd
, running
);
244 unsigned char buf
[2000];
247 size_t haveRead
= read(cfd
, buf
, 2000);
250 Data
toWrite(buf
, haveRead
);
251 vncrelay
.Send(toWrite
);
253 else if (haveRead
< 0)
259 catch( Usb::Error
&ue
) {
260 std::cout
<< endl
; // flush any normal output first
261 std::cerr
<< "Usb::Error caught: " << ue
.what() << endl
;
264 catch( Barry::Error
&se
) {
266 std::cerr
<< "Barry::Error caught: " << se
.what() << endl
;
269 catch( std::exception
&e
) {
271 std::cerr
<< "std::exception caught: " << e
.what() << endl
;