19270a20a801403c9f60d6a701b39eae70d380403Doug Zongker/*
29270a20a801403c9f60d6a701b39eae70d380403Doug Zongker * Copyright (C) 2007 The Android Open Source Project
39270a20a801403c9f60d6a701b39eae70d380403Doug Zongker *
49270a20a801403c9f60d6a701b39eae70d380403Doug Zongker * Licensed under the Apache License, Version 2.0 (the "License");
59270a20a801403c9f60d6a701b39eae70d380403Doug Zongker * you may not use this file except in compliance with the License.
69270a20a801403c9f60d6a701b39eae70d380403Doug Zongker * You may obtain a copy of the License at
79270a20a801403c9f60d6a701b39eae70d380403Doug Zongker *
89270a20a801403c9f60d6a701b39eae70d380403Doug Zongker *      http://www.apache.org/licenses/LICENSE-2.0
99270a20a801403c9f60d6a701b39eae70d380403Doug Zongker *
109270a20a801403c9f60d6a701b39eae70d380403Doug Zongker * Unless required by applicable law or agreed to in writing, software
119270a20a801403c9f60d6a701b39eae70d380403Doug Zongker * distributed under the License is distributed on an "AS IS" BASIS,
129270a20a801403c9f60d6a701b39eae70d380403Doug Zongker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139270a20a801403c9f60d6a701b39eae70d380403Doug Zongker * See the License for the specific language governing permissions and
149270a20a801403c9f60d6a701b39eae70d380403Doug Zongker * limitations under the License.
159270a20a801403c9f60d6a701b39eae70d380403Doug Zongker */
169270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
179270a20a801403c9f60d6a701b39eae70d380403Doug Zongker#define  TRACE_TAG   TRACE_ADB
189270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
199270a20a801403c9f60d6a701b39eae70d380403Doug Zongker#include <stdio.h>
209270a20a801403c9f60d6a701b39eae70d380403Doug Zongker#include <stdlib.h>
219270a20a801403c9f60d6a701b39eae70d380403Doug Zongker#include <ctype.h>
229270a20a801403c9f60d6a701b39eae70d380403Doug Zongker#include <stdarg.h>
239270a20a801403c9f60d6a701b39eae70d380403Doug Zongker#include <errno.h>
249270a20a801403c9f60d6a701b39eae70d380403Doug Zongker#include <string.h>
259270a20a801403c9f60d6a701b39eae70d380403Doug Zongker#include <time.h>
269270a20a801403c9f60d6a701b39eae70d380403Doug Zongker#include <sys/time.h>
279270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
289270a20a801403c9f60d6a701b39eae70d380403Doug Zongker#include "sysdeps.h"
299270a20a801403c9f60d6a701b39eae70d380403Doug Zongker#include "adb.h"
309270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
319270a20a801403c9f60d6a701b39eae70d380403Doug Zongker#include <private/android_filesystem_config.h>
329270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
339270a20a801403c9f60d6a701b39eae70d380403Doug Zongker#if ADB_TRACE
349270a20a801403c9f60d6a701b39eae70d380403Doug ZongkerADB_MUTEX_DEFINE( D_lock );
359270a20a801403c9f60d6a701b39eae70d380403Doug Zongker#endif
369270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
379270a20a801403c9f60d6a701b39eae70d380403Doug Zongkerint HOST = 0;
389270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
399270a20a801403c9f60d6a701b39eae70d380403Doug Zongkerstatic const char *adb_device_banner = "sideload";
409270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
419270a20a801403c9f60d6a701b39eae70d380403Doug Zongkervoid fatal(const char *fmt, ...)
429270a20a801403c9f60d6a701b39eae70d380403Doug Zongker{
439270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    va_list ap;
449270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    va_start(ap, fmt);
459270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    fprintf(stderr, "error: ");
469270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    vfprintf(stderr, fmt, ap);
479270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    fprintf(stderr, "\n");
489270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    va_end(ap);
499270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    exit(-1);
509270a20a801403c9f60d6a701b39eae70d380403Doug Zongker}
519270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
529270a20a801403c9f60d6a701b39eae70d380403Doug Zongkervoid fatal_errno(const char *fmt, ...)
539270a20a801403c9f60d6a701b39eae70d380403Doug Zongker{
549270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    va_list ap;
559270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    va_start(ap, fmt);
569270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    fprintf(stderr, "error: %s: ", strerror(errno));
579270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    vfprintf(stderr, fmt, ap);
589270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    fprintf(stderr, "\n");
599270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    va_end(ap);
609270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    exit(-1);
619270a20a801403c9f60d6a701b39eae70d380403Doug Zongker}
629270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
639270a20a801403c9f60d6a701b39eae70d380403Doug Zongkerint   adb_trace_mask;
649270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
659270a20a801403c9f60d6a701b39eae70d380403Doug Zongker/* read a comma/space/colum/semi-column separated list of tags
669270a20a801403c9f60d6a701b39eae70d380403Doug Zongker * from the ADB_TRACE environment variable and build the trace
679270a20a801403c9f60d6a701b39eae70d380403Doug Zongker * mask from it. note that '1' and 'all' are special cases to
689270a20a801403c9f60d6a701b39eae70d380403Doug Zongker * enable all tracing
699270a20a801403c9f60d6a701b39eae70d380403Doug Zongker */
709270a20a801403c9f60d6a701b39eae70d380403Doug Zongkervoid  adb_trace_init(void)
719270a20a801403c9f60d6a701b39eae70d380403Doug Zongker{
729270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    const char*  p = getenv("ADB_TRACE");
739270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    const char*  q;
749270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
759270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    static const struct {
769270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        const char*  tag;
779270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        int           flag;
789270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    } tags[] = {
799270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        { "1", 0 },
809270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        { "all", 0 },
819270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        { "adb", TRACE_ADB },
829270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        { "sockets", TRACE_SOCKETS },
839270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        { "packets", TRACE_PACKETS },
849270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        { "rwx", TRACE_RWX },
859270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        { "usb", TRACE_USB },
869270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        { "sync", TRACE_SYNC },
879270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        { "sysdeps", TRACE_SYSDEPS },
889270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        { "transport", TRACE_TRANSPORT },
899270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        { "jdwp", TRACE_JDWP },
909270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        { "services", TRACE_SERVICES },
919270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        { NULL, 0 }
929270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    };
939270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
949270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    if (p == NULL)
959270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            return;
969270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
979270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    /* use a comma/column/semi-colum/space separated list */
989270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    while (*p) {
999270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        int  len, tagn;
1009270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
1019270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        q = strpbrk(p, " ,:;");
1029270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        if (q == NULL) {
1039270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            q = p + strlen(p);
1049270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        }
1059270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        len = q - p;
1069270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
1079270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        for (tagn = 0; tags[tagn].tag != NULL; tagn++)
1089270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        {
1099270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            int  taglen = strlen(tags[tagn].tag);
1109270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
1119270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            if (len == taglen && !memcmp(tags[tagn].tag, p, len) )
1129270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            {
1139270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                int  flag = tags[tagn].flag;
1149270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                if (flag == 0) {
1159270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                    adb_trace_mask = ~0;
1169270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                    return;
1179270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                }
1189270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                adb_trace_mask |= (1 << flag);
1199270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                break;
1209270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            }
1219270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        }
1229270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        p = q;
1239270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        if (*p)
1249270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            p++;
1259270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
1269270a20a801403c9f60d6a701b39eae70d380403Doug Zongker}
1279270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
1289270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
1299270a20a801403c9f60d6a701b39eae70d380403Doug Zongkerapacket *get_apacket(void)
1309270a20a801403c9f60d6a701b39eae70d380403Doug Zongker{
1319270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    apacket *p = malloc(sizeof(apacket));
1329270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    if(p == 0) fatal("failed to allocate an apacket");
1339270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    memset(p, 0, sizeof(apacket) - MAX_PAYLOAD);
1349270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    return p;
1359270a20a801403c9f60d6a701b39eae70d380403Doug Zongker}
1369270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
1379270a20a801403c9f60d6a701b39eae70d380403Doug Zongkervoid put_apacket(apacket *p)
1389270a20a801403c9f60d6a701b39eae70d380403Doug Zongker{
1399270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    free(p);
1409270a20a801403c9f60d6a701b39eae70d380403Doug Zongker}
1419270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
1429270a20a801403c9f60d6a701b39eae70d380403Doug Zongkervoid handle_online(void)
1439270a20a801403c9f60d6a701b39eae70d380403Doug Zongker{
1449270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    D("adb: online\n");
1459270a20a801403c9f60d6a701b39eae70d380403Doug Zongker}
1469270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
1479270a20a801403c9f60d6a701b39eae70d380403Doug Zongkervoid handle_offline(atransport *t)
1489270a20a801403c9f60d6a701b39eae70d380403Doug Zongker{
1499270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    D("adb: offline\n");
1509270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    //Close the associated usb
1519270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    run_transport_disconnects(t);
1529270a20a801403c9f60d6a701b39eae70d380403Doug Zongker}
1539270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
1549270a20a801403c9f60d6a701b39eae70d380403Doug Zongker#if TRACE_PACKETS
1559270a20a801403c9f60d6a701b39eae70d380403Doug Zongker#define DUMPMAX 32
1569270a20a801403c9f60d6a701b39eae70d380403Doug Zongkervoid print_packet(const char *label, apacket *p)
1579270a20a801403c9f60d6a701b39eae70d380403Doug Zongker{
1589270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    char *tag;
1599270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    char *x;
1609270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    unsigned count;
1619270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
1629270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    switch(p->msg.command){
1639270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    case A_SYNC: tag = "SYNC"; break;
1649270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    case A_CNXN: tag = "CNXN" ; break;
1659270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    case A_OPEN: tag = "OPEN"; break;
1669270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    case A_OKAY: tag = "OKAY"; break;
1679270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    case A_CLSE: tag = "CLSE"; break;
1689270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    case A_WRTE: tag = "WRTE"; break;
1699270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    default: tag = "????"; break;
1709270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
1719270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
1729270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    fprintf(stderr, "%s: %s %08x %08x %04x \"",
1739270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            label, tag, p->msg.arg0, p->msg.arg1, p->msg.data_length);
1749270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    count = p->msg.data_length;
1759270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    x = (char*) p->data;
1769270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    if(count > DUMPMAX) {
1779270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        count = DUMPMAX;
1789270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        tag = "\n";
1799270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    } else {
1809270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        tag = "\"\n";
1819270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
1829270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    while(count-- > 0){
1839270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        if((*x >= ' ') && (*x < 127)) {
1849270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            fputc(*x, stderr);
1859270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        } else {
1869270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            fputc('.', stderr);
1879270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        }
1889270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        x++;
1899270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
1909270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    fprintf(stderr, tag);
1919270a20a801403c9f60d6a701b39eae70d380403Doug Zongker}
1929270a20a801403c9f60d6a701b39eae70d380403Doug Zongker#endif
1939270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
1949270a20a801403c9f60d6a701b39eae70d380403Doug Zongkerstatic void send_ready(unsigned local, unsigned remote, atransport *t)
1959270a20a801403c9f60d6a701b39eae70d380403Doug Zongker{
1969270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    D("Calling send_ready \n");
1979270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    apacket *p = get_apacket();
1989270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    p->msg.command = A_OKAY;
1999270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    p->msg.arg0 = local;
2009270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    p->msg.arg1 = remote;
2019270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    send_packet(p, t);
2029270a20a801403c9f60d6a701b39eae70d380403Doug Zongker}
2039270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
2049270a20a801403c9f60d6a701b39eae70d380403Doug Zongkerstatic void send_close(unsigned local, unsigned remote, atransport *t)
2059270a20a801403c9f60d6a701b39eae70d380403Doug Zongker{
2069270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    D("Calling send_close \n");
2079270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    apacket *p = get_apacket();
2089270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    p->msg.command = A_CLSE;
2099270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    p->msg.arg0 = local;
2109270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    p->msg.arg1 = remote;
2119270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    send_packet(p, t);
2129270a20a801403c9f60d6a701b39eae70d380403Doug Zongker}
2139270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
2149270a20a801403c9f60d6a701b39eae70d380403Doug Zongkerstatic void send_connect(atransport *t)
2159270a20a801403c9f60d6a701b39eae70d380403Doug Zongker{
2169270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    D("Calling send_connect \n");
2179270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    apacket *cp = get_apacket();
2189270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    cp->msg.command = A_CNXN;
2199270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    cp->msg.arg0 = A_VERSION;
2209270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    cp->msg.arg1 = MAX_PAYLOAD;
2219270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    snprintf((char*) cp->data, sizeof cp->data, "%s::",
2229270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            HOST ? "host" : adb_device_banner);
2239270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    cp->msg.data_length = strlen((char*) cp->data) + 1;
2249270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    send_packet(cp, t);
2259270a20a801403c9f60d6a701b39eae70d380403Doug Zongker}
2269270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
2279270a20a801403c9f60d6a701b39eae70d380403Doug Zongkervoid parse_banner(char *banner, atransport *t)
2289270a20a801403c9f60d6a701b39eae70d380403Doug Zongker{
2299270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    char *type, *product, *end;
2309270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
2319270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    D("parse_banner: %s\n", banner);
2329270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    type = banner;
2339270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    product = strchr(type, ':');
2349270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    if(product) {
2359270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        *product++ = 0;
2369270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    } else {
2379270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        product = "";
2389270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
2399270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
2409270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        /* remove trailing ':' */
2419270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    end = strchr(product, ':');
2429270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    if(end) *end = 0;
2439270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
2449270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        /* save product name in device structure */
2459270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    if (t->product == NULL) {
2469270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        t->product = strdup(product);
2479270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    } else if (strcmp(product, t->product) != 0) {
2489270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        free(t->product);
2499270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        t->product = strdup(product);
2509270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
2519270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
2529270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    if(!strcmp(type, "bootloader")){
2539270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        D("setting connection_state to CS_BOOTLOADER\n");
2549270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        t->connection_state = CS_BOOTLOADER;
2559270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        update_transports();
2569270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        return;
2579270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
2589270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
2599270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    if(!strcmp(type, "device")) {
2609270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        D("setting connection_state to CS_DEVICE\n");
2619270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        t->connection_state = CS_DEVICE;
2629270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        update_transports();
2639270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        return;
2649270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
2659270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
2669270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    if(!strcmp(type, "recovery")) {
2679270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        D("setting connection_state to CS_RECOVERY\n");
2689270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        t->connection_state = CS_RECOVERY;
2699270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        update_transports();
2709270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        return;
2719270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
2729270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
2739270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    if(!strcmp(type, "sideload")) {
2749270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        D("setting connection_state to CS_SIDELOAD\n");
2759270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        t->connection_state = CS_SIDELOAD;
2769270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        update_transports();
2779270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        return;
2789270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
2799270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
2809270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    t->connection_state = CS_HOST;
2819270a20a801403c9f60d6a701b39eae70d380403Doug Zongker}
2829270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
2839270a20a801403c9f60d6a701b39eae70d380403Doug Zongkervoid handle_packet(apacket *p, atransport *t)
2849270a20a801403c9f60d6a701b39eae70d380403Doug Zongker{
2859270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    asocket *s;
2869270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
2879270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    D("handle_packet() %c%c%c%c\n", ((char*) (&(p->msg.command)))[0],
2889270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            ((char*) (&(p->msg.command)))[1],
2899270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            ((char*) (&(p->msg.command)))[2],
2909270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            ((char*) (&(p->msg.command)))[3]);
2919270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    print_packet("recv", p);
2929270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
2939270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    switch(p->msg.command){
2949270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    case A_SYNC:
2959270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        if(p->msg.arg0){
2969270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            send_packet(p, t);
2979270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            if(HOST) send_connect(t);
2989270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        } else {
2999270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            t->connection_state = CS_OFFLINE;
3009270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            handle_offline(t);
3019270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            send_packet(p, t);
3029270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        }
3039270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        return;
3049270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
3059270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    case A_CNXN: /* CONNECT(version, maxdata, "system-id-string") */
3069270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            /* XXX verify version, etc */
3079270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        if(t->connection_state != CS_OFFLINE) {
3089270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            t->connection_state = CS_OFFLINE;
3099270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            handle_offline(t);
3109270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        }
3119270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        parse_banner((char*) p->data, t);
3129270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        handle_online();
3139270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        if(!HOST) send_connect(t);
3149270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        break;
3159270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
3169270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    case A_OPEN: /* OPEN(local-id, 0, "destination") */
3179270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        if(t->connection_state != CS_OFFLINE) {
3189270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            char *name = (char*) p->data;
3199270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            name[p->msg.data_length > 0 ? p->msg.data_length - 1 : 0] = 0;
3209270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            s = create_local_service_socket(name);
3219270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            if(s == 0) {
3229270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                send_close(0, p->msg.arg0, t);
3239270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            } else {
3249270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                s->peer = create_remote_socket(p->msg.arg0, t);
3259270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                s->peer->peer = s;
3269270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                send_ready(s->id, s->peer->id, t);
3279270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                s->ready(s);
3289270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            }
3299270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        }
3309270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        break;
3319270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
3329270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    case A_OKAY: /* READY(local-id, remote-id, "") */
3339270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        if(t->connection_state != CS_OFFLINE) {
3349270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            if((s = find_local_socket(p->msg.arg1))) {
3359270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                if(s->peer == 0) {
3369270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                    s->peer = create_remote_socket(p->msg.arg0, t);
3379270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                    s->peer->peer = s;
3389270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                }
3399270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                s->ready(s);
3409270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            }
3419270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        }
3429270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        break;
3439270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
3449270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    case A_CLSE: /* CLOSE(local-id, remote-id, "") */
3459270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        if(t->connection_state != CS_OFFLINE) {
3469270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            if((s = find_local_socket(p->msg.arg1))) {
3479270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                s->close(s);
3489270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            }
3499270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        }
3509270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        break;
3519270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
3529270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    case A_WRTE:
3539270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        if(t->connection_state != CS_OFFLINE) {
3549270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            if((s = find_local_socket(p->msg.arg1))) {
3559270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                unsigned rid = p->msg.arg0;
3569270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                p->len = p->msg.data_length;
3579270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
3589270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                if(s->enqueue(s, p) == 0) {
3599270a20a801403c9f60d6a701b39eae70d380403