<commit_before>/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
   Copyright (C) 2010 Red Hat, Inc.

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <arpa/inet.h>
#include <vscard_common.h>

#include "reds.h"
#include "char_device.h"
#include "red_channel.h"
#include "smartcard.h"

#define SMARTCARD_MAX_READERS 10

typedef struct SmartCardDeviceState {
    SpiceCharDeviceState base;
    uint32_t             reader_id;
    uint32_t             attached;
    uint8_t             *buf;
    uint32_t             buf_size;
    uint8_t             *buf_pos;
    uint32_t             buf_used;
    RedChannelClient    *rcc; // client providing the remote card
} SmartCardDeviceState;

enum {
    PIPE_ITEM_TYPE_ERROR=1,
    PIPE_ITEM_TYPE_MSG,
};

typedef struct ErrorItem {
    PipeItem base;
    VSCMsgHeader vheader;
    VSCMsgError  error;
} ErrorItem;

typedef struct MsgItem {
    PipeItem base;
    VSCMsgHeader* vheader;
} MsgItem;

typedef struct SmartCardChannel {
    RedChannel base;
} SmartCardChannel;

static struct Readers {
    uint32_t num;
    SpiceCharDeviceInstance* sin[SMARTCARD_MAX_READERS];
} g_smartcard_readers = {0, {NULL}};

static SpiceCharDeviceInstance* smartcard_readers_get_unattached(void);
static SpiceCharDeviceInstance* smartcard_readers_get(uint32_t reader_id);
static int smartcard_char_device_add_to_readers(SpiceCharDeviceInstance *sin);
static void smartcard_char_device_attach(
    SpiceCharDeviceInstance *char_device, RedChannelClient *rcc);
static void smartcard_char_device_detach(SpiceCharDeviceInstance *char_device);
static void smartcard_channel_write_to_reader(VSCMsgHeader *vheader);

static void smartcard_char_device_on_message_from_device(
    SmartCardDeviceState *state, VSCMsgHeader *header);
static void smartcard_on_message_from_device(
    RedChannelClient *rcc, VSCMsgHeader *vheader);
static SmartCardDeviceState* smartcard_device_state_new(void);
static void smartcard_device_state_free(SmartCardDeviceState* st);
static void smartcard_init(void);

void smartcard_char_device_wakeup(SpiceCharDeviceInstance *sin)
{
    SmartCardDeviceState* state = SPICE_CONTAINEROF(
                            sin->st, SmartCardDeviceState, base);
    SpiceCharDeviceInterface *sif = SPICE_CONTAINEROF(sin->base.sif, SpiceCharDeviceInterface, base);
    VSCMsgHeader *vheader = (VSCMsgHeader*)state->buf;
    int n;
    int remaining;
    int actual_length;

    while ((n = sif->read(sin, state->buf_pos, state->buf_size - state->buf_used)) > 0) {
        state->buf_pos += n;
        state->buf_used += n;
        if (state->buf_used < sizeof(VSCMsgHeader)) {
            continue;
        }
        actual_length = ntohl(vheader->length);
        if (actual_length > state->buf_size) {
            state->buf_size = MAX(state->buf_size*2, actual_length + sizeof(VSCMsgHeader));
            state->buf = spice_realloc(state->buf, state->buf_size);
            spice_assert(state->buf != NULL);
        }
        if (state->buf_used - sizeof(VSCMsgHeader) < actual_length) {
            continue;
        }
        smartcard_char_device_on_message_from_device(state, vheader);
        remaining = state->buf_used - sizeof(VSCMsgHeader) > actual_length;
        if (remaining > 0) {
            memcpy(state->buf, state->buf_pos, remaining);
        }
        state->buf_pos = state->buf;
        state->buf_used = remaining;
    }
}

void smartcard_char_device_on_message_from_device(
    SmartCardDeviceState *state,
    VSCMsgHeader *vheader)
{
    VSCMsgHeader *sent_header;

    vheader->type = ntohl(vheader->type);
    vheader->length = ntohl(vheader->length);<commit_msg>smartcard: fix calc of remaining data size when reading more than one msg from the device<commit_after>/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
   Copyright (C) 2010 Red Hat, Inc.

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <arpa/inet.h>
#include <vscard_common.h>

#include "reds.h"
#include "char_device.h"
#include "red_channel.h"
#include "smartcard.h"

#define SMARTCARD_MAX_READERS 10

typedef struct SmartCardDeviceState {
    SpiceCharDeviceState base;
    uint32_t             reader_id;
    uint32_t             attached;
    uint8_t             *buf;
    uint32_t             buf_size;
    uint8_t             *buf_pos;
    uint32_t             buf_used;
    RedChannelClient    *rcc; // client providing the remote card
} SmartCardDeviceState;

enum {
    PIPE_ITEM_TYPE_ERROR=1,
    PIPE_ITEM_TYPE_MSG,
};

typedef struct ErrorItem {
    PipeItem base;
    VSCMsgHeader vheader;
    VSCMsgError  error;
} ErrorItem;

typedef struct MsgItem {
    PipeItem base;
    VSCMsgHeader* vheader;
} MsgItem;

typedef struct SmartCardChannel {
    RedChannel base;
} SmartCardChannel;

static struct Readers {
    uint32_t num;
    SpiceCharDeviceInstance* sin[SMARTCARD_MAX_READERS];
} g_smartcard_readers = {0, {NULL}};

static SpiceCharDeviceInstance* smartcard_readers_get_unattached(void);
static SpiceCharDeviceInstance* smartcard_readers_get(uint32_t reader_id);
static int smartcard_char_device_add_to_readers(SpiceCharDeviceInstance *sin);
static void smartcard_char_device_attach(
    SpiceCharDeviceInstance *char_device, RedChannelClient *rcc);
static void smartcard_char_device_detach(SpiceCharDeviceInstance *char_device);
static void smartcard_channel_write_to_reader(VSCMsgHeader *vheader);

static void smartcard_char_device_on_message_from_device(
    SmartCardDeviceState *state, VSCMsgHeader *header);
static void smartcard_on_message_from_device(
    RedChannelClient *rcc, VSCMsgHeader *vheader);
static SmartCardDeviceState* smartcard_device_state_new(void);
static void smartcard_device_state_free(SmartCardDeviceState* st);
static void smartcard_init(void);

void smartcard_char_device_wakeup(SpiceCharDeviceInstance *sin)
{
    SmartCardDeviceState* state = SPICE_CONTAINEROF(
                            sin->st, SmartCardDeviceState, base);
    SpiceCharDeviceInterface *sif = SPICE_CONTAINEROF(sin->base.sif, SpiceCharDeviceInterface, base);
    VSCMsgHeader *vheader = (VSCMsgHeader*)state->buf;
    int n;
    int remaining;
    int actual_length;

    while ((n = sif->read(sin, state->buf_pos, state->buf_size - state->buf_used)) > 0) {
        state->buf_pos += n;
        state->buf_used += n;
        if (state->buf_used < sizeof(VSCMsgHeader)) {
            continue;
        }
        actual_length = ntohl(vheader->length);
        if (actual_length > state->buf_size) {
            state->buf_size = MAX(state->buf_size*2, actual_length + sizeof(VSCMsgHeader));
            state->buf = spice_realloc(state->buf, state->buf_size);
            spice_assert(state->buf != NULL);
        }
        if (state->buf_used - sizeof(VSCMsgHeader) < actual_length) {
            continue;
        }
        smartcard_char_device_on_message_from_device(state, vheader);
        remaining = state->buf_used - sizeof(VSCMsgHeader) - actual_length;
        if (remaining > 0) {
            memcpy(state->buf, state->buf_pos, remaining);
        }
        state->buf_pos = state->buf;
        state->buf_used = remaining;
    }
}

void smartcard_char_device_on_message_from_device(
    SmartCardDeviceState *state,
    VSCMsgHeader *vheader)
{
    VSCMsgHeader *sent_header;

    vheader->type = ntohl(vheader->type);
    vheader->length = ntohl(vheader->length);
{'fraction_non_alphanumeric': 0.08679202017885806, 'fraction_numerical': 0.006420545746388443, 'mean_word_length': 3.598313125988403, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 76, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4075236', 'n_tokens_mistral': 2768, 'n_tokens_neox': 2711, 'n_words': 678}