do_socket_read(GIOChannel *source,

               GIOCondition condition,

               gpointer data)

{

    int rv;

    int dwSendLength;

    int dwRecvLength;

    uint8_t pbRecvBuffer[APDUBufSize];

    static uint8_t pbSendBuffer[APDUBufSize];

    VReaderStatus reader_status;

    VReader *reader = NULL;

    static VSCMsgHeader mhHeader;

    VSCMsgError *error_msg;

    GError *err = NULL;



    static gchar *buf;

    static gsize br, to_read;

    static int state = STATE_HEADER;



    if (state == STATE_HEADER && to_read == 0) {

        buf = (gchar *)&mhHeader;

        to_read = sizeof(mhHeader);

    }



    if (to_read > 0) {

        g_io_channel_read_chars(source, (gchar *)buf, to_read, &br, &err);

        if (err != NULL) {

            g_error("error while reading: %s", err->message);

        }

        buf += br;

        to_read -= br;

        if (to_read != 0) {

            return TRUE;

        }

    }



    if (state == STATE_HEADER) {

        mhHeader.type = ntohl(mhHeader.type);

        mhHeader.reader_id = ntohl(mhHeader.reader_id);

        mhHeader.length = ntohl(mhHeader.length);

        if (verbose) {

            printf("Header: type=%d, reader_id=%u length=%d (0x%x)\n",

                   mhHeader.type, mhHeader.reader_id, mhHeader.length,

                   mhHeader.length);

        }

        switch (mhHeader.type) {

        case VSC_APDU:

        case VSC_Flush:

        case VSC_Error:

        case VSC_Init:

            buf = (gchar *)pbSendBuffer;

            to_read = mhHeader.length;

            state = STATE_MESSAGE;

            return TRUE;

        default:

            fprintf(stderr, "Unexpected message of type 0x%X\n", mhHeader.type);

            return FALSE;

        }

    }



    if (state == STATE_MESSAGE) {

        switch (mhHeader.type) {

        case VSC_APDU:

            if (verbose) {

                printf(" recv APDU: ");

                print_byte_array(pbSendBuffer, mhHeader.length);

            }

            /* Transmit received APDU */

            dwSendLength = mhHeader.length;

            dwRecvLength = sizeof(pbRecvBuffer);

            reader = vreader_get_reader_by_id(mhHeader.reader_id);

            reader_status = vreader_xfr_bytes(reader,

                                              pbSendBuffer, dwSendLength,

                                              pbRecvBuffer, &dwRecvLength);

            if (reader_status == VREADER_OK) {

                mhHeader.length = dwRecvLength;

                if (verbose) {

                    printf(" send response: ");

                    print_byte_array(pbRecvBuffer, mhHeader.length);

                }

                send_msg(VSC_APDU, mhHeader.reader_id,

                         pbRecvBuffer, dwRecvLength);

            } else {

                rv = reader_status; /* warning: not meaningful */

                send_msg(VSC_Error, mhHeader.reader_id, &rv, sizeof(uint32_t));

            }

            vreader_free(reader);

            reader = NULL; /* we've freed it, don't use it by accident

                              again */

            break;

        case VSC_Flush:

            /* TODO: actually flush */

            send_msg(VSC_FlushComplete, mhHeader.reader_id, NULL, 0);

            break;

        case VSC_Error:

            error_msg = (VSCMsgError *) pbSendBuffer;

            if (error_msg->code == VSC_SUCCESS) {

                qemu_mutex_lock(&pending_reader_lock);

                if (pending_reader) {

                    vreader_set_id(pending_reader, mhHeader.reader_id);

                    vreader_free(pending_reader);

                    pending_reader = NULL;

                    qemu_cond_signal(&pending_reader_condition);

                }

                qemu_mutex_unlock(&pending_reader_lock);

                break;

            }

            printf("warning: qemu refused to add reader\n");

            if (error_msg->code == VSC_CANNOT_ADD_MORE_READERS) {

                /* clear pending reader, qemu can't handle any more */

                qemu_mutex_lock(&pending_reader_lock);

                if (pending_reader) {

                    pending_reader = NULL;

                    /* make sure the event loop doesn't hang */

                    qemu_cond_signal(&pending_reader_condition);

                }

                qemu_mutex_unlock(&pending_reader_lock);

            }

            break;

        case VSC_Init:

            if (on_host_init(&mhHeader, (VSCMsgInit *)pbSendBuffer) < 0) {

                return FALSE;

            }

            break;

        default:

            g_assert_not_reached();

            return FALSE;

        }



        state = STATE_HEADER;

    }





    return TRUE;

}

do_socket_read(GIOChannel *source,

               GIOCondition condition,

               gpointer data)

{

    int rv;

    int dwSendLength;

    int dwRecvLength;

    uint8_t pbRecvBuffer[APDUBufSize];

    static uint8_t pbSendBuffer[APDUBufSize];

    VReaderStatus reader_status;

    VReader *reader = NULL;

    static VSCMsgHeader mhHeader;

    VSCMsgError *error_msg;

    GError *err = NULL;



    static gchar *buf;

    static gsize br, to_read;

    static int state = STATE_HEADER;



    if (state == STATE_HEADER && to_read == 0) {

        buf = (gchar *)&mhHeader;

        to_read = sizeof(mhHeader);

    }



    if (to_read > 0) {

        g_io_channel_read_chars(source, (gchar *)buf, to_read, &br, &err);

        if (err != NULL) {

            g_error("error while reading: %s", err->message);

        }

        buf += br;

        to_read -= br;

        if (to_read != 0) {

            return TRUE;

        }

    }



    if (state == STATE_HEADER) {

        mhHeader.type = ntohl(mhHeader.type);

        mhHeader.reader_id = ntohl(mhHeader.reader_id);

        mhHeader.length = ntohl(mhHeader.length);

        if (verbose) {

            printf("Header: type=%d, reader_id=%u length=%d (0x%x)\n",

                   mhHeader.type, mhHeader.reader_id, mhHeader.length,

                   mhHeader.length);

        }

        switch (mhHeader.type) {

        case VSC_APDU:

        case VSC_Flush:

        case VSC_Error:

        case VSC_Init:

            buf = (gchar *)pbSendBuffer;

            to_read = mhHeader.length;

            state = STATE_MESSAGE;

            return TRUE;

        default:

            fprintf(stderr, "Unexpected message of type 0x%X\n", mhHeader.type);

            return FALSE;

        }

    }



    if (state == STATE_MESSAGE) {

        switch (mhHeader.type) {

        case VSC_APDU:

            if (verbose) {

                printf(" recv APDU: ");

                print_byte_array(pbSendBuffer, mhHeader.length);

            }

            

            dwSendLength = mhHeader.length;

            dwRecvLength = sizeof(pbRecvBuffer);

            reader = vreader_get_reader_by_id(mhHeader.reader_id);

            reader_status = vreader_xfr_bytes(reader,

                                              pbSendBuffer, dwSendLength,

                                              pbRecvBuffer, &dwRecvLength);

            if (reader_status == VREADER_OK) {

                mhHeader.length = dwRecvLength;

                if (verbose) {

                    printf(" send response: ");

                    print_byte_array(pbRecvBuffer, mhHeader.length);

                }

                send_msg(VSC_APDU, mhHeader.reader_id,

                         pbRecvBuffer, dwRecvLength);

            } else {

                rv = reader_status; 

                send_msg(VSC_Error, mhHeader.reader_id, &rv, sizeof(uint32_t));

            }

            vreader_free(reader);

            reader = NULL; 



            break;

        case VSC_Flush:

            

            send_msg(VSC_FlushComplete, mhHeader.reader_id, NULL, 0);

            break;

        case VSC_Error:

            error_msg = (VSCMsgError *) pbSendBuffer;

            if (error_msg->code == VSC_SUCCESS) {

                qemu_mutex_lock(&pending_reader_lock);

                if (pending_reader) {

                    vreader_set_id(pending_reader, mhHeader.reader_id);

                    vreader_free(pending_reader);

                    pending_reader = NULL;

                    qemu_cond_signal(&pending_reader_condition);

                }

                qemu_mutex_unlock(&pending_reader_lock);

                break;

            }

            printf("warning: qemu refused to add reader\n");

            if (error_msg->code == VSC_CANNOT_ADD_MORE_READERS) {

                

                qemu_mutex_lock(&pending_reader_lock);

                if (pending_reader) {

                    pending_reader = NULL;

                    

                    qemu_cond_signal(&pending_reader_condition);

                }

                qemu_mutex_unlock(&pending_reader_lock);

            }

            break;

        case VSC_Init:

            if (on_host_init(&mhHeader, (VSCMsgInit *)pbSendBuffer) < 0) {

                return FALSE;

            }

            break;

        default:

            g_assert_not_reached();

            return FALSE;

        }



        state = STATE_HEADER;

    }





    return TRUE;

}

FUNC_0(GIOChannel *VAR_0,

               GIOCondition VAR_1,

               gpointer VAR_2)

{

    int VAR_3;

    int VAR_4;

    int VAR_5;

    uint8_t pbRecvBuffer[APDUBufSize];

    static uint8_t VAR_6[APDUBufSize];

    VReaderStatus reader_status;

    VReader *reader = NULL;

    static VSCMsgHeader VAR_7;

    VSCMsgError *error_msg;

    GError *err = NULL;



    static gchar *VAR_8;

    static gsize VAR_9, to_read;

    static int VAR_10 = STATE_HEADER;



    if (VAR_10 == STATE_HEADER && to_read == 0) {

        VAR_8 = (gchar *)&VAR_7;

        to_read = sizeof(VAR_7);

    }



    if (to_read > 0) {

        g_io_channel_read_chars(VAR_0, (gchar *)VAR_8, to_read, &VAR_9, &err);

        if (err != NULL) {

            g_error("error while reading: %s", err->message);

        }

        VAR_8 += VAR_9;

        to_read -= VAR_9;

        if (to_read != 0) {

            return TRUE;

        }

    }



    if (VAR_10 == STATE_HEADER) {

        VAR_7.type = ntohl(VAR_7.type);

        VAR_7.reader_id = ntohl(VAR_7.reader_id);

        VAR_7.length = ntohl(VAR_7.length);

        if (verbose) {

            printf("Header: type=%d, reader_id=%u length=%d (0x%x)\n",

                   VAR_7.type, VAR_7.reader_id, VAR_7.length,

                   VAR_7.length);

        }

        switch (VAR_7.type) {

        case VSC_APDU:

        case VSC_Flush:

        case VSC_Error:

        case VSC_Init:

            VAR_8 = (gchar *)VAR_6;

            to_read = VAR_7.length;

            VAR_10 = STATE_MESSAGE;

            return TRUE;

        default:

            fprintf(stderr, "Unexpected message of type 0x%X\n", VAR_7.type);

            return FALSE;

        }

    }



    if (VAR_10 == STATE_MESSAGE) {

        switch (VAR_7.type) {

        case VSC_APDU:

            if (verbose) {

                printf(" recv APDU: ");

                print_byte_array(VAR_6, VAR_7.length);

            }

            

            VAR_4 = VAR_7.length;

            VAR_5 = sizeof(pbRecvBuffer);

            reader = vreader_get_reader_by_id(VAR_7.reader_id);

            reader_status = vreader_xfr_bytes(reader,

                                              VAR_6, VAR_4,

                                              pbRecvBuffer, &VAR_5);

            if (reader_status == VREADER_OK) {

                VAR_7.length = VAR_5;

                if (verbose) {

                    printf(" send response: ");

                    print_byte_array(pbRecvBuffer, VAR_7.length);

                }

                send_msg(VSC_APDU, VAR_7.reader_id,

                         pbRecvBuffer, VAR_5);

            } else {

                VAR_3 = reader_status; 

                send_msg(VSC_Error, VAR_7.reader_id, &VAR_3, sizeof(uint32_t));

            }

            vreader_free(reader);

            reader = NULL; 



            break;

        case VSC_Flush:

            

            send_msg(VSC_FlushComplete, VAR_7.reader_id, NULL, 0);

            break;

        case VSC_Error:

            error_msg = (VSCMsgError *) VAR_6;

            if (error_msg->code == VSC_SUCCESS) {

                qemu_mutex_lock(&pending_reader_lock);

                if (pending_reader) {

                    vreader_set_id(pending_reader, VAR_7.reader_id);

                    vreader_free(pending_reader);

                    pending_reader = NULL;

                    qemu_cond_signal(&pending_reader_condition);

                }

                qemu_mutex_unlock(&pending_reader_lock);

                break;

            }

            printf("warning: qemu refused to add reader\n");

            if (error_msg->code == VSC_CANNOT_ADD_MORE_READERS) {

                

                qemu_mutex_lock(&pending_reader_lock);

                if (pending_reader) {

                    pending_reader = NULL;

                    

                    qemu_cond_signal(&pending_reader_condition);

                }

                qemu_mutex_unlock(&pending_reader_lock);

            }

            break;

        case VSC_Init:

            if (on_host_init(&VAR_7, (VSCMsgInit *)VAR_6) < 0) {

                return FALSE;

            }

            break;

        default:

            g_assert_not_reached();

            return FALSE;

        }



        VAR_10 = STATE_HEADER;

    }





    return TRUE;

}

FUNC_0(GIOChannel *VAR_0,
GIOCondition VAR_1,
gpointer VAR_2)
{ int VAR_3; int VAR_4; int VAR_5; uint8_t pbRecvBuffer[APDUBufSize]; static uint8_t VAR_6[APDUBufSize]; VReaderStatus reader_status; VReader *reader = NULL; static VSCMsgHeader VAR_7; VSCMsgError *error_msg; GError *err = NULL; static gchar *VAR_8; static gsize VAR_9, to_read; static int VAR_10 = STATE_HEADER; if (VAR_10 == STATE_HEADER && to_read == 0) { VAR_8 = (gchar *)&VAR_7; to_read = sizeof(VAR_7); } if (to_read > 0) { g_io_channel_read_chars(VAR_0, (gchar *)VAR_8, to_read, &VAR_9, &err); if (err != NULL) { g_error("error while reading: %s", err->message); } VAR_8 += VAR_9; to_read -= VAR_9; if (to_read != 0) { return TRUE; } } if (VAR_10 == STATE_HEADER) { VAR_7.type = ntohl(VAR_7.type); VAR_7.reader_id = ntohl(VAR_7.reader_id); VAR_7.length = ntohl(VAR_7.length); if (verbose) { printf("Header: type=%d, reader_id=%u length=%d (0x%x)\n",
VAR_7.type, VAR_7.reader_id, VAR_7.length,
VAR_7.length); } switch (VAR_7.type) { case VSC_APDU:
case VSC_Flush:
case VSC_Error:
case VSC_Init:
VAR_8 = (gchar *)VAR_6; to_read = VAR_7.length; VAR_10 = STATE_MESSAGE; return TRUE; default:
fprintf(stderr, "Unexpected message of type 0x%X\n", VAR_7.type); return FALSE; } } if (VAR_10 == STATE_MESSAGE) { switch (VAR_7.type) { case VSC_APDU:
if (verbose) { printf(" recv APDU: "); print_byte_array(VAR_6, VAR_7.length); } VAR_4 = VAR_7.length; VAR_5 = sizeof(pbRecvBuffer); reader = vreader_get_reader_by_id(VAR_7.reader_id); reader_status = vreader_xfr_bytes(reader,
VAR_6, VAR_4,
pbRecvBuffer, &VAR_5); if (reader_status == VREADER_OK) { VAR_7.length = VAR_5; if (verbose) { printf(" send response: "); print_byte_array(pbRecvBuffer, VAR_7.length); } send_msg(VSC_APDU, VAR_7.reader_id,
pbRecvBuffer, VAR_5); } else { VAR_3 = reader_status; send_msg(VSC_Error, VAR_7.reader_id, &VAR_3, sizeof(uint32_t)); } vreader_free(reader); reader = NULL; break; case VSC_Flush:
send_msg(VSC_FlushComplete, VAR_7.reader_id, NULL, 0); break; case VSC_Error:
error_msg = (VSCMsgError *) VAR_6; if (error_msg->code == VSC_SUCCESS) { qemu_mutex_lock(&pending_reader_lock); if (pending_reader) { vreader_set_id(pending_reader, VAR_7.reader_id); vreader_free(pending_reader); pending_reader = NULL; qemu_cond_signal(&pending_reader_condition); } qemu_mutex_unlock(&pending_reader_lock); break; } printf("warning: qemu refused to add reader\n"); if (error_msg->code == VSC_CANNOT_ADD_MORE_READERS) { qemu_mutex_lock(&pending_reader_lock); if (pending_reader) { pending_reader = NULL; qemu_cond_signal(&pending_reader_condition); } qemu_mutex_unlock(&pending_reader_lock); } break; case VSC_Init:
if (on_host_init(&VAR_7, (VSCMsgInit *)VAR_6) < 0) { return FALSE; } break; default:
g_assert_not_reached(); return FALSE; } VAR_10 = STATE_HEADER; } return TRUE; }