⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sockets.c

📁 Android 一些工具
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <errno.h>#include <string.h>#include <ctype.h>#include "sysdeps.h"#define  TRACE_TAG  TRACE_SOCKETS#include "adb.h"ADB_MUTEX_DEFINE( socket_list_lock );static void local_socket_close_locked(asocket *s);int sendfailmsg(int fd, const char *reason){    char buf[9];    int len;    len = strlen(reason);    if(len > 0xffff) len = 0xffff;    snprintf(buf, sizeof buf, "FAIL%04x", len);    if(writex(fd, buf, 8)) return -1;    return writex(fd, reason, len);}//extern int online;static unsigned local_socket_next_id = 1;static asocket local_socket_list = {    .next = &local_socket_list,    .prev = &local_socket_list,};asocket *find_local_socket(unsigned id){    asocket *s;    asocket *result = NULL;    adb_mutex_lock(&socket_list_lock);    for(s = local_socket_list.next; s != &local_socket_list && !result; s = s->next) {        if(s->id == id) result = s;    }    adb_mutex_unlock(&socket_list_lock);    return result;}void install_local_socket(asocket *s){    adb_mutex_lock(&socket_list_lock);    s->id = local_socket_next_id++;    s->next = &local_socket_list;    s->prev = local_socket_list.prev;    s->prev->next = s;    s->next->prev = s;    adb_mutex_unlock(&socket_list_lock);}void remove_socket(asocket *s){    // socket_list_lock should already be held    if (s->prev && s->next)    {        s->prev->next = s->next;        s->next->prev = s->prev;        s->next = 0;        s->prev = 0;        s->id = 0;    }}void close_all_sockets(atransport *t){    asocket *s;        /* this is a little gross, but since s->close() *will* modify        ** the list out from under you, your options are limited.        */    adb_mutex_lock(&socket_list_lock);restart:    for(s = local_socket_list.next; s != &local_socket_list; s = s->next){        if(s->transport == t || (s->peer && s->peer->transport == t)) {            local_socket_close_locked(s);            goto restart;        }    }    adb_mutex_unlock(&socket_list_lock);}static int local_socket_enqueue(asocket *s, apacket *p){    D("LS(%d): enqueue %d\n", s->id, p->len);    p->ptr = p->data;        /* if there is already data queue'd, we will receive        ** events when it's time to write.  just add this to        ** the tail        */    if(s->pkt_first) {        goto enqueue;    }        /* write as much as we can, until we        ** would block or there is an error/eof        */    while(p->len > 0) {        int r = adb_write(s->fd, p->ptr, p->len);        if(r > 0) {            p->len -= r;            p->ptr += r;            continue;        }        if((r == 0) || (errno != EAGAIN)) {            D( "LS(%d): not ready, errno=%d: %s\n", s->id, errno, strerror(errno) );            s->close(s);            return 1; /* not ready (error) */        } else {            break;        }    }    if(p->len == 0) {        put_apacket(p);        return 0; /* ready for more data */    }enqueue:    p->next = 0;    if(s->pkt_first) {        s->pkt_last->next = p;    } else {        s->pkt_first = p;    }    s->pkt_last = p;        /* make sure we are notified when we can drain the queue */    fdevent_add(&s->fde, FDE_WRITE);    return 1; /* not ready (backlog) */}static void local_socket_ready(asocket *s){        /* far side is ready for data, pay attention to           readable events */    fdevent_add(&s->fde, FDE_READ);//    D("LS(%d): ready()\n", s->id);}static void local_socket_close(asocket *s){    adb_mutex_lock(&socket_list_lock);    local_socket_close_locked(s);    adb_mutex_unlock(&socket_list_lock);}static void local_socket_close_locked(asocket *s){    apacket *p, *n;    if(s->peer) {        s->peer->peer = 0;        // tweak to avoid deadlock        if (s->peer->close == local_socket_close)            local_socket_close_locked(s->peer);        else            s->peer->close(s->peer);    }        /* IMPORTANT: the remove closes the fd        ** that belongs to this socket        */    fdevent_remove(&s->fde);        /* dispose of any unwritten data */    for(p = s->pkt_first; p; p = n) {        D("LS(%d): discarding %d bytes\n", s->id, p->len);        n = p->next;        put_apacket(p);    }    D("LS(%d): closed\n", s->id);    remove_socket(s);    free(s);}static void local_socket_event_func(int fd, unsigned ev, void *_s){    asocket *s = _s;    if(ev & FDE_READ){        apacket *p = get_apacket();        unsigned char *x = p->data;        size_t avail = MAX_PAYLOAD;        int r;        int is_eof = 0;        while(avail > 0) {            r = adb_read(fd, x, avail);            if(r > 0) {                avail -= r;                x += r;                continue;            }            if(r < 0) {                if(errno == EAGAIN) break;                if(errno == EINTR) continue;            }                /* r = 0 or unhandled error */            is_eof = 1;            break;        }        if((avail == MAX_PAYLOAD) || (s->peer == 0)) {            put_apacket(p);        } else {            p->len = MAX_PAYLOAD - avail;            r = s->peer->enqueue(s->peer, p);            if(r < 0) {                    /* error return means they closed us as a side-effect                    ** and we must retutn immediately                    */                return;            }            if(r > 0) {                    /* if the remote cannot accept further events,                    ** we disable notification of READs.  They'll                    ** be enabled again when we get a call to ready()                    */                fdevent_del(&s->fde, FDE_READ);            }        }        if(is_eof) {            s->close(s);        }        return;    }    if(ev & FDE_WRITE){        apacket *p;        while((p = s->pkt_first) != 0) {            while(p->len > 0) {                int r = adb_write(fd, p->ptr, p->len);                if(r > 0) {                    p->ptr += r;                    p->len -= r;                    continue;                }                if(r < 0) {                    if(errno == EAGAIN) return;                    if(errno == EINTR) continue;                }                s->close(s);                return;            }            if(p->len == 0) {                s->pkt_first = p->next;                if(s->pkt_first == 0) s->pkt_last = 0;                put_apacket(p);            }        }            /* no more packets queued, so we can ignore            ** writable events again and tell our peer            ** to resume writing            */        fdevent_del(&s->fde, FDE_WRITE);        s->peer->ready(s->peer);        return;    }    if(ev & FDE_ERROR){            /* this should be caught be the next read or write            ** catching it here means we may skip the last few            ** bytes of readable data.            *///        s->close(s);        return;    }}asocket *create_local_socket(int fd){    asocket *s = calloc(1, sizeof(asocket));    if(s == 0) fatal("cannot allocate socket");    install_local_socket(s);    s->fd = fd;    s->enqueue = local_socket_enqueue;    s->ready = local_socket_ready;    s->close = local_socket_close;    fdevent_install(&s->fde, fd, local_socket_event_func, s);/*    fdevent_add(&s->fde, FDE_ERROR); */    //fprintf(stderr, "Created local socket in create_local_socket \n");    D("LS(%d): created (fd=%d)\n", s->id, s->fd);    return s;}asocket *create_local_service_socket(const char *name){    asocket *s;    int fd;#if !ADB_HOST    if (!strcmp(name,"jdwp")) {        return create_jdwp_service_socket();    }    if (!strcmp(name,"track-jdwp")) {        return create_jdwp_tracker_service_socket();    }#endif    fd = service_to_fd(name);    if(fd < 0) return 0;    s = create_local_socket(fd);    D("LS(%d): bound to '%s'\n", s->id, name);    return s;}#if ADB_HOSTstatic asocket *create_host_service_socket(const char *name, const char* serial){    asocket *s;    s = host_service_to_socket(name, serial);    if (s != NULL) {        D("LS(%d) bound to '%s'\n", s->id, name);        return s;    }    return s;}#endif /* ADB_HOST *//* a Remote socket is used to send/receive data to/from a given transport object** it needs to be closed when the transport is forcibly destroyed by the user

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -