Exemple #1
0
void cache_wait(AbstractCache * cache) {
#else
void cache_wait_dbg(const char * file, int line, AbstractCache * cache) {
#endif
    assert(is_dispatch_thread());
    assert(current_client.client != NULL);
    if (current_client.client != NULL) {
        current_cache = cache;
        cache_miss_cnt++;
#ifndef NDEBUG
        current_client.file = file;
        current_client.line = line;
        current_client.time_stamp = time(NULL);
        if (!cache_timer_posted) {
            post_event_with_delay(cache_timer, NULL, 5000000);
            cache_timer_posted = 1;
        }
#endif
    }
#ifndef NDEBUG
    else {
        trace(LOG_ALWAYS, "Illegal cache access at %s:%d", file, line);
    }
#endif
    exception(ERR_CACHE_MISS);
}
static int tcp_is_closed(Channel * channel) {
    ChannelTCP * c = channel2tcp(channel);
    assert(is_dispatch_thread());
    assert(c->magic == CHANNEL_MAGIC);
    assert(c->lock_cnt > 0);
    return c->socket < 0;
}
Exemple #3
0
void cache_wait(AbstractCache * cache) {
#else
void cache_wait_dbg(const char * file, int line, AbstractCache * cache) {
#endif
    assert(is_dispatch_thread());
    assert(client_exited == 0);
    if (current_client.client != NULL && cache_miss_cnt == 0) {
        if (cache->wait_list_cnt >= cache->wait_list_max) {
            cache->wait_list_max += 8;
            cache->wait_list_buf = (WaitingCacheClient *)loc_realloc(cache->wait_list_buf, cache->wait_list_max * sizeof(WaitingCacheClient));
        }
        if (current_client.args != NULL && !current_client.args_copy) {
            void * mem = loc_alloc(current_client.args_size);
            memcpy(mem, current_client.args, current_client.args_size);
            current_client.args = mem;
            current_client.args_copy = 1;
        }
#ifndef NDEBUG
        current_client.file = file;
        current_client.line = line;
#endif
        if (cache->wait_list_cnt == 0) list_add_last(&cache->link, &cache_list);
        cache->wait_list_buf[cache->wait_list_cnt++] = current_client;
        channel_lock(current_client.channel);
    }
#ifndef NDEBUG
    else if (current_client.client == NULL) {
        trace(LOG_ALWAYS, "cache_wait(): illegal cache access at %s:%d", file, line);
    }
#endif
    cache_miss_cnt++;
    exception(ERR_CACHE_MISS);
}
Exemple #4
0
static void realloc_msg_buf(void) {
    assert(is_dispatch_thread());
    if (msg_buf_max <= msg_buf_len + 128 || msg_buf_max > msg_buf_len + 2048) {
        msg_buf_max = msg_buf_len + 256;
        msg_buf = (char *)loc_realloc(msg_buf, msg_buf_max);
    }
}
static int send_packet(PortConnection * conn, char * buffer, size_t size) {
    JsonWriteBinaryState state;

    assert (is_dispatch_thread());
    assert (conn->pending_write_request < MAX_STREAM_WRITE);
    protocol_send_command(conn->server->channel, "Streams", "write", write_stream_done,
            conn);
    json_write_string(&conn->server->channel->out, conn->out_stream_id);
    write_stream(&conn->server->channel->out, 0);
    json_write_long(&conn->server->channel->out, size);
    write_stream(&conn->server->channel->out, MARKER_EOA);
    json_write_binary_start(&state, &conn->server->channel->out, size);
    json_write_binary_data(&state, buffer, size);
    json_write_binary_end(&state);
    write_stream(&conn->server->channel->out, MARKER_EOA);
    write_stream(&conn->server->channel->out, MARKER_EOM);
    conn->pending_write_request ++;
    if (conn->pending_write_request  == MAX_STREAM_WRITE) {
        return 0;
    }
    else {
        send_packet_callback(conn, 0);
    }
    return 0;
}
Exemple #6
0
void cache_exit(void) {
    assert(is_dispatch_thread());
    assert(current_client.client != NULL);
    assert(!client_exited);
    if (cache_miss_cnt > 0) exception(ERR_CACHE_MISS);
    client_exited = 1;
}
Exemple #7
0
static char * system_strerror(DWORD error_code, HMODULE module) {
    WCHAR * buf = NULL;
    assert(is_dispatch_thread());
    msg_buf_len = 0;
    if (FormatMessageW(
            FORMAT_MESSAGE_ALLOCATE_BUFFER |
            FORMAT_MESSAGE_FROM_SYSTEM |
            FORMAT_MESSAGE_IGNORE_INSERTS |
            FORMAT_MESSAGE_MAX_WIDTH_MASK |
            (module ? FORMAT_MESSAGE_FROM_HMODULE : 0),
            module,
            error_code,
            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
            (LPWSTR)&buf, 0, NULL)) {
        msg_buf_len = WideCharToMultiByte(CP_UTF8, 0, buf, -1, NULL, 0, NULL, NULL);
        if (msg_buf_len > 0) {
            realloc_msg_buf();
            msg_buf_len = WideCharToMultiByte(CP_UTF8, 0, buf, -1, msg_buf, (int)msg_buf_max, NULL, NULL);
        }
    }
    if (msg_buf_len == 0) {
        realloc_msg_buf();
        msg_buf_len = snprintf(msg_buf, msg_buf_max, "System error code 0x%08x", (unsigned)error_code);
    }
    if (buf != NULL) LocalFree(buf);
    while (msg_buf_len > 0 && msg_buf[msg_buf_len - 1] <= ' ') msg_buf_len--;
    if (msg_buf_len > 0 && msg_buf[msg_buf_len - 1] == '.') msg_buf_len--;
    msg_buf[msg_buf_len] = 0;
    return msg_buf;
}
Exemple #8
0
static void clear_stale_peers(void * x) {
    PeerServer ** sp = &peers;
    PeerServer * s;
    time_t timenow = time(NULL);
    int keep_timer = 0;

    assert(is_dispatch_thread());
    while ((s = *sp) != NULL) {
        if (s->expiration_time <= timenow) {
            /* Delete stale entry */
            *sp = s->next;
            notify_listeners(s, PS_EVENT_REMOVED);
            s->listed = 0;
            peer_server_free(s);
        }
        else {
            keep_timer = 1;
            sp = &s->next;
        }
    }
    if (keep_timer) {
        post_event_with_delay(clear_stale_peers, NULL, PEER_DATA_REFRESH_PERIOD * 1000000);
    }
    else {
        stale_timer_active = 0;
    }
}
Exemple #9
0
void * tmp_alloc(size_t size) {
    void * p;
    LINK * l;
    assert(is_dispatch_thread());
    if (!tmp_gc_posted) {
        post_event(gc_event, NULL);
        tmp_gc_posted = 1;
    }
#if ENABLE_FastMemAlloc
    if (tmp_pool_pos + size + ALIGNMENT + sizeof(size_t *) > tmp_pool_max) {
        if (tmp_pool != NULL) {
            l = (LINK *)tmp_pool;
            list_add_last(l, &tmp_alloc_list);
            tmp_alloc_size += tmp_pool_pos;
        }
        tmp_pool_max = POOL_SIZE / 0x10 + size;
        tmp_pool = (char *)loc_alloc(tmp_pool_max);
        tmp_pool_pos = sizeof(LINK);
    }
    tmp_pool_pos += sizeof(size_t *);
    tmp_pool_pos = (tmp_pool_pos + ALIGNMENT - 1) & ~(ALIGNMENT - 1);
    p = tmp_pool + tmp_pool_pos;
    *((size_t *)p - 1) = size;
    tmp_pool_pos += size;
    return p;
#else
    l = (LINK *)loc_alloc(sizeof(LINK) + size);
    list_add_last(l, &tmp_alloc_list);
    tmp_alloc_size += size + ALIGNMENT + sizeof(size_t *);
    p = l + 1;
    return p;
#endif
}
Exemple #10
0
void cache_dispose(AbstractCache * cache) {
    assert(is_dispatch_thread());
    assert(cache->wait_list_cnt == 0);
    assert(list_is_empty(&cache->link));
    loc_free(cache->wait_list_buf);
    memset(cache, 0, sizeof(*cache));
}
static void np_channel_read_done(void * x) {
    AsyncReqInfo * req = (AsyncReqInfo *)x;
    ChannelNP * c = (ChannelNP *)req->client_data;
    ssize_t len = 0;

    assert(is_dispatch_thread());
    assert(c->magic == CHANNEL_MAGIC);
    assert(c->read_pending != 0);
    assert(c->lock_cnt > 0);
    loc_free(req->u.user.data);

    c->read_pending = 0;
    /* some data is available retrieve it */
    {
        len = c->rd_req.u.user.rval;
        if (req->error) {
            if (c->chan.state != ChannelStateDisconnected) {
                trace(LOG_ALWAYS, "Can't read from socket: %s", errno_to_str(req->error));
            }
            len = 0; /* Treat error as EOF */
        }
    }
    if (c->chan.state != ChannelStateDisconnected) {
        ibuf_read_done(&c->ibuf, len);
    }
    else if (len > 0) {
        np_post_read(&c->ibuf, c->ibuf.buf, c->ibuf.buf_size);
    }
    else {
        np_unlock(&c->chan);
    }
}
Exemple #12
0
int set_trap_a(Trap * trap) {
    assert(is_dispatch_thread());
    memset(trap, 0, sizeof(Trap));
    trap->next = chain;
    chain = trap;
    return 0;
}
static int np_is_closed(Channel * channel) {
    ChannelNP * c = channel2np(channel);
    assert(is_dispatch_thread());
    assert(c->magic == CHANNEL_MAGIC);
    assert(c->lock_cnt > 0);
    return c->chan.state == ChannelStateDisconnected;
}
Exemple #14
0
static int pipe_is_closed(Channel * channel) {
    ChannelPIPE * c = channel2pipe(channel);
    assert(is_dispatch_thread());
    assert(c->magic == CHANNEL_MAGIC);
    assert(c->lock_cnt > 0);
    return c->chan->state == ChannelStateDisconnected;
}
static void handle_channel_msg(void * x) {
    Trap trap;
    ChannelNP * c = (ChannelNP *)x;
    int has_msg;

    assert(is_dispatch_thread());
    assert(c->magic == CHANNEL_MAGIC);
    assert(c->ibuf.handling_msg == HandleMsgTriggered);
    assert(c->ibuf.message_count);

    has_msg = ibuf_start_message(&c->ibuf);
    if (has_msg <= 0) {
        if (has_msg < 0 && c->chan.state != ChannelStateDisconnected) {
            trace(LOG_PROTOCOL, "Socket is shutdown by remote peer, channel %#lx %s", c, c->chan.peer_name);
            channel_close(&c->chan);
        }
    }
    else if (set_trap(&trap)) {
        if (c->chan.receive) {
            c->chan.receive(&c->chan);
        }
        else {
            handle_protocol_message(&c->chan);
            assert(c->out_bin_block == NULL);
        }
        clear_trap(&trap);
    }
    else {
        trace(LOG_ALWAYS, "Exception in message handler: %s", errno_to_str(trap.error));
        send_eof_and_close(&c->chan, trap.error);
    }
}
Exemple #16
0
int context_read_mem(Context * ctx, ContextAddress address, void * buf, size_t size) {
    ContextAddress word_addr;
    unsigned word_size = context_word_size(ctx);
    assert(is_dispatch_thread());
    assert(!ctx->exited);
    trace(LOG_CONTEXT, "context: read memory ctx %#lx, id %s, address %#lx, size %zu",
        ctx, ctx->id, address, size);
    assert(word_size <= sizeof(unsigned long));
    for (word_addr = address & ~((ContextAddress)word_size - 1); word_addr < address + size; word_addr += word_size) {
        unsigned long word = 0;
        errno = 0;
        word = ptrace(PTRACE_PEEKDATA, EXT(ctx)->pid, (char *)word_addr, 0);
        if (errno != 0) {
            int err = errno;
            trace(LOG_CONTEXT, "error: ptrace(PTRACE_PEEKDATA, ...) failed: ctx %#lx, id %s, addr %#lx, error %d %s",
                ctx, ctx->id, word_addr, err, errno_to_str(err));
            errno = err;
            return -1;
        }
        if (word_addr < address || word_addr + word_size > address + size) {
            size_t i;
            for (i = 0; i < word_size; i++) {
                if (word_addr + i >= address && word_addr + i < address + size) {
                    ((char *)buf)[word_addr + i - address] = ((char *)&word)[i];
                }
            }
        }
        else {
            memcpy((char *)buf + (word_addr - address), &word, word_size);
        }
    }
    return check_breakpoints_on_memory_read(ctx, address, buf, size);
}
Exemple #17
0
static void tcp_flush_with_flags(ChannelTCP * c, int flags) {
    unsigned char * p = c->obuf;
    assert(is_dispatch_thread());
    assert(c->magic == CHANNEL_MAGIC);
    assert(c->chan.out.end == p + sizeof(c->obuf));
    assert(c->out_bin_block == NULL);
    assert(c->chan.out.cur >= p);
    assert(c->chan.out.cur <= p + sizeof(c->obuf));
    if (c->chan.out.cur == p) return;
    if (c->chan.state != ChannelStateDisconnected && c->out_errno == 0) {
#if ENABLE_OutputQueue
        c->out_queue.post_io_request = post_write_request;
        output_queue_add(&c->out_queue, p, c->chan.out.cur - p);
#else
        assert(c->ssl == NULL);
        while (p < c->chan.out.cur) {
            size_t sz = c->chan.out.cur - p;
            ssize_t wr = send(c->socket, p, sz, flags);
            if (wr < 0) {
                int err = errno;
                trace(LOG_PROTOCOL, "Can't send() on channel %#lx: %s", c, errno_to_str(err));
                c->out_errno = err;
                c->chan.out.cur = c->obuf;
                return;
            }
            p += wr;
        }
        assert(p == c->chan.out.cur);
#endif
    }
    c->chan.out.cur = c->obuf;
}
Exemple #18
0
void * tmp_realloc(void * ptr, size_t size) {
    if (ptr == NULL) return tmp_alloc(size);
    assert(is_dispatch_thread());
    assert(tmp_gc_posted);
#if ENABLE_FastMemAlloc
    {
        void * p;
        size_t m = *((size_t *)ptr - 1);
        if (m >= size) return ptr;
        if ((char *)ptr >= tmp_pool && (char *)ptr <= tmp_pool + tmp_pool_max) {
            size_t pos = tmp_pool_pos - m;
            if (ptr == tmp_pool + pos && pos + size <= tmp_pool_max) {
                tmp_pool_pos = pos + size;
                *((size_t *)ptr - 1) = size;
                return ptr;
            }
        }
        p = tmp_alloc(size);
        if (m > size) m = size;
        return memcpy(p, ptr, m);
    }
#else
    {
        LINK * l = (LINK *)ptr - 1;
        list_remove(l);
        l = (LINK *)loc_realloc(l, sizeof(LINK) + size);
        list_add_last(l, &tmp_alloc_list);
        return l + 1;
    }
#endif
}
static void connect_port_callback(PortConnection * conn, int error) {
    assert(is_dispatch_thread());
    port_unlock(conn);
    if (conn->shutdown_in_progress) return;
    if (error != 0) {
        port_connection_close(conn);
        return;
    }
    else {
        int idx;
        if (conn->server->connect_callback) conn->server->connect_callback(conn->server, conn->server->callback_data);
        conn->connected = 1;
        if (conn->fd != -1) {
            port_lock(conn);
            conn->recv_req.u.sio.sock = conn->fd;
            conn->recv_req.u.sio.addr = &conn->server->client_addr;
            conn->recv_req.u.sio.addrlen = sizeof(conn->server->client_addr);
            async_req_post(&conn->recv_req);
        }
        /* Send multiple TCF streams read requests in parallel; this is
         * to limit the performance impact on network with high latency.
         */
        for (idx = 0; idx < MAX_STREAM_READ; idx++) 
            read_packet(conn, idx);
    }
}
Exemple #20
0
int set_win32_errno(DWORD win32_error_code) {
    if (win32_error_code == 0) return errno = 0;
    if (win32_error_code >= ERR_WINDOWS_CNT) {
        if (!is_dispatch_thread()) return errno = ERR_OTHER;
        return set_errno(ERR_OTHER, system_strerror(win32_error_code, NULL));
    }
    return errno = ERR_WINDOWS_MIN + win32_error_code;
}
static void tcp_flush_with_flags(OutputStream * out, int flags) {
    int cnt = 0;
    ChannelTCP * c = channel2tcp(out2channel(out));
    assert(is_dispatch_thread());
    assert(c->magic == CHANNEL_MAGIC);
    assert(c->obuf_inp <= BUF_SIZE);
    if (c->obuf_inp == 0) return;
    if (c->socket < 0 || c->out_errno) {
        c->obuf_inp = 0;
        return;
    }
    while (cnt < c->obuf_inp) {
        int wr = 0;
        if (c->ssl) {
#if ENABLE_SSL
            wr = SSL_write(c->ssl, c->obuf + cnt, c->obuf_inp - cnt);
            if (wr <= 0) {
                int err = SSL_get_error(c->ssl, wr);
                if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
                    struct timeval tv;
                    fd_set readfds;
                    fd_set writefds;
                    fd_set errorfds;
                    FD_ZERO(&readfds);
                    FD_ZERO(&writefds);
                    FD_ZERO(&errorfds);
                    if (err == SSL_ERROR_WANT_READ) FD_SET(c->socket, &readfds);
                    if (err == SSL_ERROR_WANT_WRITE) FD_SET(c->socket, &writefds);
                    FD_SET(c->socket, &errorfds);
                    tv.tv_sec = 10L;
                    tv.tv_usec = 0;
                    if (select(c->socket + 1, &readfds, &writefds, &errorfds, &tv) >= 0) continue;
                }
                trace(LOG_PROTOCOL, "Can't SSL_write() on channel %#lx: %s", c,
                    ERR_error_string(ERR_get_error(), NULL));
                c->out_errno = EIO;
                c->obuf_inp = 0;
                return;
            }
#else
            assert(0);
#endif
        }
        else {
            wr = send(c->socket, c->obuf + cnt, c->obuf_inp - cnt, flags);
            if (wr < 0) {
                int err = errno;
                trace(LOG_PROTOCOL, "Can't send() on channel %#lx: %d %s", c, err, errno_to_str(err));
                c->out_errno = err;
                c->obuf_inp = 0;
                return;
            }
        }
        cnt += wr;
    }
    assert(cnt == c->obuf_inp);
    c->obuf_inp = 0;
}
static void channel_check_pending(Channel * channel) {
    ChannelNP * c = channel2np(channel);

    assert(is_dispatch_thread());
    if (c->ibuf.handling_msg == HandleMsgIdle && c->ibuf.message_count) {
        post_event(handle_channel_msg, c);
        c->ibuf.handling_msg = HandleMsgTriggered;
    }
}
Exemple #23
0
/* Find peer server based on ID */
PeerServer * peer_server_find(const char * id) {
    PeerServer * s;

    assert(is_dispatch_thread());
    for (s = peers; s != NULL; s = s->next) {
        if (strcmp(s->id, id) == 0) return s;
    }
    return NULL;
}
Exemple #24
0
void release_error_report(ErrorReport * r) {
    if (r != NULL) {
        ReportBuffer * report = (ReportBuffer *)((char *)r - offsetof(ReportBuffer, pub));
        assert(is_dispatch_thread());
        assert(report->gets > 0);
        report->gets--;
        release_report(report);
    }
}
Exemple #25
0
int context_continue(Context * ctx) {
    int signal = 0;

    assert(is_dispatch_thread());
    assert(ctx->stopped);
    assert(!ctx->pending_intercept);
    assert(!EXT(ctx)->pending_step);
    assert(!ctx->exited);

    if (skip_breakpoint(ctx, 0)) return 0;

    if (!EXT(ctx)->ptrace_event) {
        while (ctx->pending_signals != 0) {
            while ((ctx->pending_signals & (1 << signal)) == 0) signal++;
            if (ctx->sig_dont_pass & (1 << signal)) {
                ctx->pending_signals &= ~(1 << signal);
                signal = 0;
            }
            else {
                break;
            }
        }
        assert(signal != SIGSTOP);
        assert(signal != SIGTRAP);
    }

    trace(LOG_CONTEXT, "context: resuming ctx %#lx, id %s, with signal %d", ctx, ctx->id, signal);
    if (EXT(ctx)->regs_dirty) {
        if (ptrace(PTRACE_SETREGS, EXT(ctx)->pid, 0, (int)EXT(ctx)->regs) < 0) {
            int err = errno;
            if (err == ESRCH) {
                EXT(ctx)->regs_dirty = 0;
                send_context_started_event(ctx);
                return 0;
            }
            trace(LOG_ALWAYS, "error: ptrace(PTRACE_SETREGS) failed: ctx %#lx, id %s, error %d %s",
                ctx, ctx->id, err, errno_to_str(err));
            errno = err;
            return -1;
        }
        EXT(ctx)->regs_dirty = 0;
    }
    if (ptrace(PTRACE_CONT, EXT(ctx)->pid, 0, signal) < 0) {
        int err = errno;
        if (err == ESRCH) {
            send_context_started_event(ctx);
            return 0;
        }
        trace(LOG_ALWAYS, "error: ptrace(PTRACE_CONT, ...) failed: ctx %#lx, id %s, error %d %s",
            ctx, ctx->id, err, errno_to_str(err));
        errno = err;
        return -1;
    }
    ctx->pending_signals &= ~(1 << signal);
    send_context_started_event(ctx);
    return 0;
}
Exemple #26
0
static void signal_handler(int sig) {
    if (is_dispatch_thread()) {
        discovery_stop();
        signal(sig, SIG_DFL);
        raise(sig);
    }
    else {
        post_event(shutdown_event, NULL);
    }
}
static void tcp_unlock(Channel * channel) {
    ChannelTCP * c = channel2tcp(channel);
    assert(is_dispatch_thread());
    assert(c->magic == CHANNEL_MAGIC);
    assert(c->lock_cnt > 0);
    c->lock_cnt--;
    if (c->lock_cnt == 0 && !c->read_pending) {
        delete_channel(c);
    }
}
static void np_trigger_message(InputBuf * ibuf) {
    ChannelNP * c = ibuf2np(ibuf);

    assert(is_dispatch_thread());
    assert(c->ibuf.message_count > 0);
    if (c->ibuf.handling_msg == HandleMsgIdle) {
        post_event(handle_channel_msg, c);
        c->ibuf.handling_msg = HandleMsgTriggered;
    }
}
static void disconnect_port(PortConnection * conn) {
    assert (is_dispatch_thread());
    conn->shutdown_in_progress = 1;
    port_lock(conn);
    protocol_send_command(conn->server->channel, "PortForward", "delete",
            delete_config_done, conn);
    json_write_string(&conn->server->channel->out, conn->id);
    write_stream(&conn->server->channel->out, MARKER_EOA);
    write_stream(&conn->server->channel->out, MARKER_EOM);
}
Exemple #30
0
void cache_exit(void) {
    unsigned i;
    assert(is_dispatch_thread());
    assert(current_client.client != NULL);
    if (cache_miss_cnt > 0) exception(ERR_CACHE_MISS);
    for (i = 0; i < listeners_cnt; i++) listeners[i](CTLE_COMMIT);
    memset(&current_client, 0, sizeof(current_client));
    current_cache = NULL;
    cache_miss_cnt = 0;
    def_channel = NULL;
}