summaryrefslogtreecommitdiffstats
path: root/remoting/client/simple_client.cc
diff options
context:
space:
mode:
Diffstat (limited to 'remoting/client/simple_client.cc')
-rw-r--r--remoting/client/simple_client.cc196
1 files changed, 196 insertions, 0 deletions
diff --git a/remoting/client/simple_client.cc b/remoting/client/simple_client.cc
new file mode 100644
index 0000000..ff74312
--- /dev/null
+++ b/remoting/client/simple_client.cc
@@ -0,0 +1,196 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// A simple client implements a minimalize Chromoting client and shows
+// network traffic for debugging.
+
+#include <iostream>
+#include <list>
+
+#include "base/at_exit.h"
+#include "base/message_loop.h"
+#include "base/stl_util-inl.h"
+#include "media/base/data_buffer.h"
+#include "remoting/base/protocol_decoder.h"
+#include "remoting/client/host_connection.h"
+#include "remoting/jingle_glue/jingle_channel.h"
+#include "remoting/jingle_glue/jingle_client.h"
+
+using chromotocol_pb::HostMessage;
+using chromotocol_pb::InitClientMessage;
+using chromotocol_pb::BeginUpdateStreamMessage;
+using chromotocol_pb::EndUpdateStreamMessage;
+using chromotocol_pb::UpdateStreamPacketMessage;
+using remoting::HostConnection;
+using remoting::HostMessageList;
+using remoting::JingleClient;
+using remoting::JingleChannel;
+using remoting::ProtocolDecoder;
+
+void SetConsoleEcho(bool on) {
+#ifdef WIN32
+ HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE);
+ if ((hIn == INVALID_HANDLE_VALUE) || (hIn == NULL))
+ return;
+
+ DWORD mode;
+ if (!GetConsoleMode(hIn, &mode))
+ return;
+
+ if (on) {
+ mode = mode | ENABLE_ECHO_INPUT;
+ } else {
+ mode = mode & ~ENABLE_ECHO_INPUT;
+ }
+
+ SetConsoleMode(hIn, mode);
+#else
+ if (on)
+ system("stty echo");
+ else
+ system("stty -echo");
+#endif
+}
+
+class SimpleHostEventHandler : public HostConnection::EventHandler {
+ public:
+ SimpleHostEventHandler(MessageLoop* loop)
+ : main_loop_(loop) {
+ }
+
+ virtual void HandleMessages(HostConnection* conn,
+ HostMessageList* messages) {
+ HostMessageList list;
+ messages->swap(list);
+ for (size_t i = 0; i < list.size(); ++i) {
+ HostMessage* msg = list[i];
+ if (msg->has_init_client()) {
+ HandleInitClientMessage(msg);
+ } else if (msg->has_begin_update_stream()) {
+ HandleBeginUpdateStreamMessage(msg);
+ } else if (msg->has_update_stream_packet()) {
+ HandleUpdateStreamPacketMessage(msg);
+ } else if (msg->has_end_update_stream()) {
+ HandleEndUpdateStreamMessage(msg);
+ }
+ }
+ STLDeleteElements<HostMessageList>(&list);
+ }
+
+ virtual void OnConnectionOpened(HostConnection* conn) {
+ std::cout << "Connection establised." << std::endl;
+ }
+
+ virtual void OnConnectionClosed(HostConnection* conn) {
+ std::cout << "Connection closed." << std::endl;
+
+ // Quit the message if the connection has closed.
+ DCHECK(main_loop_);
+ main_loop_->PostTask(FROM_HERE, new MessageLoop::QuitTask());
+ }
+
+ virtual void OnConnectionFailed(HostConnection* conn) {
+ std::cout << "Conection failed." << std::endl;
+
+ // Quit the message if the connection has failed.
+ DCHECK(main_loop_);
+ main_loop_->PostTask(FROM_HERE, new MessageLoop::QuitTask());
+ }
+
+ private:
+ void HandleInitClientMessage(HostMessage* host_msg) {
+ const InitClientMessage& msg = host_msg->init_client();
+ std::cout << "InitClient (" << msg.width()
+ << ", " << msg.height() << ")" << std::endl;
+ }
+
+ void HandleBeginUpdateStreamMessage(HostMessage* host_msg) {
+ const BeginUpdateStreamMessage& msg = host_msg->begin_update_stream();
+ }
+
+ void HandleUpdateStreamPacketMessage(HostMessage* host_msg) {
+ const UpdateStreamPacketMessage& msg = host_msg->update_stream_packet();
+ std::cout << "UpdateStreamPacket (" << msg.header().x()
+ << ", " << msg.header().y() << ") ["
+ << msg.header().width() << " x " << msg.header().height() << "]"
+ << std::endl;
+ }
+
+ void HandleEndUpdateStreamMessage(HostMessage* host_msg) {
+ const EndUpdateStreamMessage& msg = host_msg->end_update_stream();
+ }
+
+ // JingleClient::Callback interface.
+ void OnStateChange(JingleClient* client, JingleClient::State state) {
+ if (state == JingleClient::CONNECTED) {
+ LOG(INFO) << "Connected as: " << client->GetFullJid();
+ } else if (state == JingleClient::CLOSED) {
+ LOG(INFO) << "Connection closed.";
+ }
+ }
+
+ MessageLoop* main_loop_;
+
+ DISALLOW_COPY_AND_ASSIGN(SimpleHostEventHandler);
+};
+
+int main(int argc, char** argv) {
+ base::AtExitManager exit_manager;
+
+ if (argc > 2) {
+ std::cerr << "Usage: " << argv[0] << " [<host_jid>]" << std::endl;
+ return 1;
+ }
+
+ // Get host JID from command line arguments, or stdin if not specified.
+ std::string host_jid;
+ if (argc == 2) {
+ host_jid = argv[1];
+ } else {
+ std::cout << "Host JID: ";
+ std::cin >> host_jid;
+ std::cin.ignore(); // Consume the leftover '\n'
+ }
+ if (host_jid.find("/chromoting") == std::string::npos) {
+ std::cerr << "Error: Expected Host JID in format: <jid>/chromoting<id>"
+ << std::endl;
+ return 1;
+ }
+
+ // Get username (JID).
+ // Extract default JID from host_jid.
+ std::string username;
+ std::string default_username;
+ size_t jid_end = host_jid.find('/');
+ if (jid_end != std::string::npos) {
+ default_username = host_jid.substr(0, jid_end);
+ }
+ std::cout << "JID [" << default_username << "]: ";
+ getline(std::cin, username);
+ if (username.length() == 0) {
+ username = default_username;
+ }
+ if (username.length() == 0) {
+ std::cerr << "Error: Expected valid JID username" << std::endl;
+ return 1;
+ }
+
+ // Get password (with console echo turned off).
+ std::string password;
+ SetConsoleEcho(false);
+ std::cout << "Password: ";
+ getline(std::cin, password);
+ SetConsoleEcho(true);
+ std::cout << std::endl;
+
+ // The message loop that everything runs on.
+ MessageLoop main_loop;
+ SimpleHostEventHandler handler(&main_loop);
+ HostConnection connection(new ProtocolDecoder(), &handler);
+ connection.Connect(username, password, host_jid);
+
+ // Run the message.
+ main_loop.Run();
+ return 0;
+}