Theoretically (being the key word) code-complete relay. Definitely not working and...
[barry.git] / tools / bvncrelay.cc
blobb0a883e5afc2de636d908fe07ac377a966915747
1 ///
2 /// \file bvncrelay.cc
3 ///
4 ///
6 /*
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>
26 #include <iostream>
27 #include <vector>
28 #include <string>
29 #include <cstring>
30 #include <algorithm>
31 #include <getopt.h>
32 #include <fstream>
33 #include <string.h>
34 #include <sys/types.h>
35 #include <sys/socket.h>
36 #include <netinet/in.h>
37 #include <arpa/inet.h>
39 #include "i18n.h"
41 using namespace std;
42 using namespace Barry;
44 class TCPWriter : public Barry::Mode::VNCServerDataCallback
46 public:
47 void SetSocket(int socket, bool& keepGoing)
49 cfd = socket;
50 continuePtr = &keepGoing;
53 void DataReceived(Data& data)
55 std::cerr << "From BB: ";
56 data.DumpHex(std::cerr);
57 std::cerr << "\n";
59 size_t toWrite = data.GetSize();
60 size_t written = 0;
62 while (written < toWrite)
64 ssize_t writtenThisTime = write(cfd, &(data.GetData()[written]), toWrite - written);
65 if (writtenThisTime < 0)
67 *continuePtr = false;
69 else
71 written += writtenThisTime;
76 private:
77 bool* continuePtr;
78 int cfd;
81 void Usage()
83 int major, minor;
84 const char *Version = Barry::Version(major, minor);
86 cerr
87 << "bvncrelay - Command line USB Blackberry VNC Relay\n"
88 << " Copyright 2010, RealVNC Ltd.\n"
89 << " Using: " << Version << "\n"
90 << "\n"
91 << " -h This help\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"
97 << "\n"
98 << endl;
101 static void handle_error(const char* text)
103 throw new std::runtime_error(text);
107 int main(int argc, char *argv[])
109 INIT_I18N(PACKAGE);
111 cout.sync_with_stdio(true); // leave this on, since libusb uses
112 // stdio for debug messages
114 try {
116 uint32_t pin = 0;
117 bool list_siblings = false,
118 data_dump = false;
119 string password;
120 vector<string> params;
121 string busname;
122 string devname;
123 string iconvCharset;
124 Usb::EndpointPair epOverride;
126 // process command line options
127 for(;;) {
128 int cmd = getopt(argc, argv, "hsp:P:v");
129 if( cmd == -1 )
130 break;
132 switch( cmd )
134 case 'p': // Blackberry PIN
135 pin = strtoul(optarg, NULL, 16);
136 break;
138 case 'P': // Device password
139 password = optarg;
140 break;
142 case 's': // turn on listing of sibling modules
143 list_siblings = true;
144 break;
146 case 'v': // data dump on
147 data_dump = true;
148 break;
150 case 'h': // help
151 default:
152 Usage();
153 return 0;
157 argc -= optind;
158 argv += optind;
160 if( argc < 1 ) {
161 cerr << "missing command" << endl;
162 Usage();
163 return 1;
166 // Fetch command from remaining arguments
167 string cmd = argv[0];
168 argc --;
169 argv ++;
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
177 // anything else.
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
183 Barry::Probe probe;
184 int activeDevice = probe.FindActive(pin);
185 if( activeDevice == -1 ) {
186 cerr << "No device selected, or PIN not found" << endl;
187 return 1;
190 // Create the thing which will write onto TCP
191 TCPWriter tcpwriter;
193 // Start a thread to handle any data arriving from
194 // the BlackBerry.
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);
211 if (sfd == -1)
212 handle_error("socket");
214 sockaddr_in my_addr;
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,
234 &peer_addr_size);
235 if (cfd == -1)
236 handle_error("accept");
239 std::cerr << "Accepted\n";
241 bool running = true;
242 tcpwriter.SetSocket(cfd, running);
244 unsigned char buf[2000];
245 while (running)
247 size_t haveRead = read(cfd, buf, 2000);
248 if (haveRead > 0)
250 Data toWrite(buf, haveRead);
251 vncrelay.Send(toWrite);
253 else if (haveRead < 0)
255 running = false;
259 catch( Usb::Error &ue) {
260 std::cout << endl; // flush any normal output first
261 std::cerr << "Usb::Error caught: " << ue.what() << endl;
262 return 1;
264 catch( Barry::Error &se ) {
265 std::cout << endl;
266 std::cerr << "Barry::Error caught: " << se.what() << endl;
267 return 1;
269 catch( std::exception &e ) {
270 std::cout << endl;
271 std::cerr << "std::exception caught: " << e.what() << endl;
272 return 1;
275 return 0;