Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

ADB Enhanced Version

  • Loading branch information...
commit 99ee49916dfcc45ba8e8d8ff23e38f146077dd80 1 parent b332ddc
@sztupy sztupy authored committed
View
2  Recipe
@@ -260,7 +260,7 @@ GTKTERM = UXTERM gtkwin gtkcfg gtkdlg gtkfont gtkcols xkeysym
OSXTERM = UXTERM osxwin osxdlg osxctrls
# Non-SSH back ends (putty, puttytel, plink).
-NONSSH = telnet raw rlogin ldisc pinger
+NONSSH = telnet adb raw rlogin ldisc pinger
# SSH back end (putty, plink, pscp, psftp).
SSH = ssh sshcrc sshdes sshmd5 sshrsa sshrand sshsha sshblowf
View
342 adb.c
@@ -0,0 +1,342 @@
+/*
+ * "Adb" backend.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "putty.h"
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#define ADB_MAX_BACKLOG 4096
+
+typedef struct adb_backend_data {
+ const struct plug_function_table *fn;
+ /* the above field _must_ be first in the structure */
+
+ Socket s;
+ int bufsize;
+ void *frontend;
+ int state;
+} *Adb;
+
+static void adb_size(void *handle, int width, int height);
+
+static void c_write(Adb adb, char *buf, int len)
+{
+ int backlog = from_backend(adb->frontend, 0, buf, len);
+ sk_set_frozen(adb->s, backlog > ADB_MAX_BACKLOG);
+}
+
+static void adb_log(Plug plug, int type, SockAddr addr, int port,
+ const char *error_msg, int error_code)
+{
+ Adb adb = (Adb) plug;
+ char addrbuf[256], *msg;
+
+ sk_getaddr(addr, addrbuf, lenof(addrbuf));
+
+ if (type == 0)
+ msg = dupprintf("Connecting to %s port %d", addrbuf, port);
+ else
+ msg = dupprintf("Failed to connect to %s: %s", addrbuf, error_msg);
+
+ logevent(adb->frontend, msg);
+}
+
+static int adb_closing(Plug plug, const char *error_msg, int error_code,
+ int calling_back)
+{
+ Adb adb = (Adb) plug;
+
+ if (adb->s) {
+ sk_close(adb->s);
+ adb->s = NULL;
+ notify_remote_exit(adb->frontend);
+ }
+ if (error_msg) {
+ /* A socket error has occurred. */
+ logevent(adb->frontend, error_msg);
+ connection_fatal(adb->frontend, "%s", error_msg);
+ } /* Otherwise, the remote side closed the connection normally. */
+ return 0;
+}
+
+static int adb_receive(Plug plug, int urgent, char *data, int len)
+{
+ Adb adb = (Adb) plug;
+ if (adb->state==1) {
+ if (data[0]=='O') { // OKAY
+ sk_write(adb->s,"0006shell:",10);
+ adb->state=2; // wait for shell start response
+ } else {
+ if (data[0]=='F') {
+ char* d = (char*)smalloc(len+1);
+ memcpy(d,data,len);
+ d[len]='\0';
+ connection_fatal(adb->frontend, "%s", d+8);
+ sfree(d);
+ } else {
+ connection_fatal(adb->frontend, "Bad response");
+ }
+ return 0;
+ }
+ } else if (adb->state==2) {
+ if (data[0]=='O') { //OKAY
+ adb->state=3; // shell started, switch to terminal mode
+ } else {
+ if (data[0]=='F') {
+ char* d = (char*)smalloc(len+1);
+ memcpy(d,data,len);
+ d[len]='\0';
+ connection_fatal(adb->frontend, "%s", d+8);
+ sfree(d);
+ } else {
+ connection_fatal(adb->frontend, "Bad response");
+ }
+ return 0;
+ }
+ } else {
+ c_write(adb, data, len);
+ }
+ return 1;
+}
+
+static void adb_sent(Plug plug, int bufsize)
+{
+ Adb adb = (Adb) plug;
+ adb->bufsize = bufsize;
+}
+
+/*
+ * Called to set up the adb connection.
+ *
+ * Returns an error message, or NULL on success.
+ *
+ * Also places the canonical host name into `realhost'. It must be
+ * freed by the caller.
+ */
+static const char *adb_init(void *frontend_handle, void **backend_handle,
+ Config *cfg,
+ char *host, int port, char **realhost, int nodelay,
+ int keepalive)
+{
+ static const struct plug_function_table fn_table = {
+ adb_log,
+ adb_closing,
+ adb_receive,
+ adb_sent
+ };
+ SockAddr addr;
+ const char *err;
+ Adb adb;
+ char sendhost[512];
+
+ adb = snew(struct adb_backend_data);
+ adb->fn = &fn_table;
+ adb->s = NULL;
+ adb->state = 0;
+ *backend_handle = adb;
+
+ adb->frontend = frontend_handle;
+
+ /*
+ * Try to find host.
+ */
+ {
+ char *buf;
+ buf = dupprintf("Looking up host \"%s\"%s", "localhost",
+ (cfg->addressfamily == ADDRTYPE_IPV4 ? " (IPv4)" :
+ (cfg->addressfamily == ADDRTYPE_IPV6 ? " (IPv6)" :
+ "")));
+ logevent(adb->frontend, buf);
+ sfree(buf);
+ }
+ addr = name_lookup("localhost", port, realhost, cfg, cfg->addressfamily);
+ if ((err = sk_addr_error(addr)) != NULL) {
+ sk_addr_free(addr);
+ return err;
+ }
+
+ if (port < 0)
+ port = 5037; /* default adb port */
+
+ /*
+ * Open socket.
+ */
+ adb->s = new_connection(addr, *realhost, port, 0, 1, nodelay, keepalive,
+ (Plug) adb, cfg);
+ if ((err = sk_socket_error(adb->s)) != NULL)
+ return err;
+
+ if (*cfg->loghost) {
+ char *colon;
+
+ sfree(*realhost);
+ *realhost = dupstr(cfg->loghost);
+ colon = strrchr(*realhost, ':');
+ if (colon) {
+ /*
+ * FIXME: if we ever update this aspect of ssh.c for
+ * IPv6 literal management, this should change in line
+ * with it.
+ */
+ *colon++ = '\0';
+ }
+ }
+
+ /* send initial data to adb server */
+
+ sprintf_s(sendhost,512,"%04xhost:%s",strlen(host)+5,host);
+
+ sk_write(adb->s,sendhost,strlen(host)+9);
+ sk_flush(adb->s);
+ adb->state = 1;
+ return NULL;
+}
+
+static void adb_free(void *handle)
+{
+ Adb adb = (Adb) handle;
+
+ if (adb->s)
+ sk_close(adb->s);
+ sfree(adb);
+}
+
+/*
+ * Stub routine (we don't have any need to reconfigure this backend).
+ */
+static void adb_reconfig(void *handle, Config *cfg)
+{
+}
+
+/*
+ * Called to send data down the adb connection.
+ */
+static int adb_send(void *handle, char *buf, int len)
+{
+ Adb adb = (Adb) handle;
+
+ if (adb->s == NULL)
+ return 0;
+
+ adb->bufsize = sk_write(adb->s, buf, len);
+
+ return adb->bufsize;
+}
+
+/*
+ * Called to query the current socket sendability status.
+ */
+static int adb_sendbuffer(void *handle)
+{
+ Adb adb = (Adb) handle;
+ return adb->bufsize;
+}
+
+/*
+ * Called to set the size of the window
+ */
+static void adb_size(void *handle, int width, int height)
+{
+ /* Do nothing! */
+ return;
+}
+
+/*
+ * Send adb special codes.
+ */
+static void adb_special(void *handle, Telnet_Special code)
+{
+ /* Do nothing! */
+ return;
+}
+
+/*
+ * Return a list of the special codes that make sense in this
+ * protocol.
+ */
+static const struct telnet_special *adb_get_specials(void *handle)
+{
+ return NULL;
+}
+
+static int adb_connected(void *handle)
+{
+ Adb adb = (Adb) handle;
+ return adb->s != NULL;
+}
+
+static int adb_sendok(void *handle)
+{
+ return 1;
+}
+
+static void adb_unthrottle(void *handle, int backlog)
+{
+ Adb adb = (Adb) handle;
+ sk_set_frozen(adb->s, backlog > ADB_MAX_BACKLOG);
+}
+
+static int adb_ldisc(void *handle, int option)
+{
+ // Don't allow line discipline options
+ return 0;
+}
+
+static void adb_provide_ldisc(void *handle, void *ldisc)
+{
+ /* This is a stub. */
+}
+
+static void adb_provide_logctx(void *handle, void *logctx)
+{
+ /* This is a stub. */
+}
+
+static int adb_exitcode(void *handle)
+{
+ Adb adb = (Adb) handle;
+ if (adb->s != NULL)
+ return -1; /* still connected */
+ else
+ /* Exit codes are a meaningless concept in the Adb protocol */
+ return 0;
+}
+
+/*
+ * cfg_info for Adb does nothing at all.
+ */
+static int adb_cfg_info(void *handle)
+{
+ return 0;
+}
+
+Backend adb_backend = {
+ adb_init,
+ adb_free,
+ adb_reconfig,
+ adb_send,
+ adb_sendbuffer,
+ adb_size,
+ adb_special,
+ adb_get_specials,
+ adb_connected,
+ adb_exitcode,
+ adb_sendok,
+ adb_ldisc,
+ adb_provide_ldisc,
+ adb_provide_logctx,
+ adb_unthrottle,
+ adb_cfg_info,
+ "adb",
+ PROT_ADB,
+ 5037
+};
View
1  be_all.c
@@ -27,5 +27,6 @@ Backend *backends[] = {
&telnet_backend,
&rlogin_backend,
&raw_backend,
+ &adb_backend,
NULL
};
View
1  be_all_s.c
@@ -27,6 +27,7 @@ Backend *backends[] = {
&telnet_backend,
&rlogin_backend,
&raw_backend,
+ &adb_backend,
&serial_backend,
NULL
};
View
1  be_nos_s.c
@@ -14,6 +14,7 @@ Backend *backends[] = {
&telnet_backend,
&rlogin_backend,
&raw_backend,
+ &adb_backend,
&serial_backend,
NULL
};
View
1  be_nossh.c
@@ -14,6 +14,7 @@ Backend *backends[] = {
&telnet_backend,
&rlogin_backend,
&raw_backend,
+ &adb_backend,
NULL
};
View
6 cmdline.c
@@ -217,6 +217,12 @@ int cmdline_process_param(char *p, char *value, int need_save, Config *cfg)
SAVEABLE(0);
default_protocol = cfg->protocol = PROT_RAW;
}
+ if (!strcmp(p, "-adb")) {
+ RETURN(1);
+ UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
+ SAVEABLE(0);
+ default_protocol = cfg->protocol = PROT_ADB;
+ }
if (!strcmp(p, "-serial")) {
RETURN(1);
/* Serial is not NONNETWORK in an odd sense of the word */
View
6 config.c
@@ -1266,18 +1266,20 @@ void setup_config_box(struct controlbox *b, int midsession,
ctrl_columns(s, 1, 100);
if (!backend_from_proto(PROT_SSH)) {
- ctrl_radiobuttons(s, "Connection type:", NO_SHORTCUT, 3,
+ ctrl_radiobuttons(s, "Connection type:", NO_SHORTCUT, 4,
HELPCTX(session_hostname),
config_protocolbuttons_handler, P(hp),
"Raw", 'w', I(PROT_RAW),
+ "Adb", 'a', I(PROT_ADB),
"Telnet", 't', I(PROT_TELNET),
"Rlogin", 'i', I(PROT_RLOGIN),
NULL);
} else {
- ctrl_radiobuttons(s, "Connection type:", NO_SHORTCUT, 4,
+ ctrl_radiobuttons(s, "Connection type:", NO_SHORTCUT, 5,
HELPCTX(session_hostname),
config_protocolbuttons_handler, P(hp),
"Raw", 'w', I(PROT_RAW),
+ "Adb", 'b', I(PROT_ADB),
"Telnet", 't', I(PROT_TELNET),
"Rlogin", 'i', I(PROT_RLOGIN),
"SSH", 's', I(PROT_SSH),
View
8 putty.h
@@ -332,7 +332,7 @@ enum {
PROT_RAW, PROT_TELNET, PROT_RLOGIN, PROT_SSH,
/* PROT_SERIAL is supported on a subset of platforms, but it doesn't
* hurt to define it globally. */
- PROT_SERIAL
+ PROT_SERIAL, PROT_ADB
};
enum {
@@ -1026,6 +1026,12 @@ extern Backend loop_backend;
extern Backend raw_backend;
/*
+ * Exports from adb.c.
+ */
+
+extern Backend adb_backend;
+
+/*
* Exports from rlogin.c.
*/
Please sign in to comment.
Something went wrong with that request. Please try again.