Loading libcacard/vscclient.c +246 −145 Original line number Diff line number Diff line Loading @@ -10,7 +10,10 @@ * See the COPYING.LIB file in the top-level directory. */ #ifndef _WIN32 #include <netdb.h> #endif #include <glib.h> #include "qemu-common.h" #include "qemu/thread.h" Loading @@ -22,9 +25,7 @@ #include "vcard_emul.h" #include "vevent.h" int verbose; int sock; static int verbose; static void print_byte_array( Loading @@ -51,7 +52,47 @@ print_usage(void) { vcard_emul_usage(); } static QemuMutex write_lock; static GIOChannel *channel_socket; static GByteArray *socket_to_send; static QemuMutex socket_to_send_lock; static guint socket_tag; static void update_socket_watch(gboolean out); static gboolean do_socket_send(GIOChannel *source, GIOCondition condition, gpointer data) { gsize bw; GError *err = NULL; g_return_val_if_fail(socket_to_send->len != 0, FALSE); g_return_val_if_fail(condition & G_IO_OUT, FALSE); g_io_channel_write_chars(channel_socket, (gchar *)socket_to_send->data, socket_to_send->len, &bw, &err); if (err != NULL) { g_error("Error while sending socket %s", err->message); return FALSE; } g_byte_array_remove_range(socket_to_send, 0, bw); if (socket_to_send->len == 0) { update_socket_watch(FALSE); return FALSE; } return TRUE; } static gboolean socket_prepare_sending(gpointer user_data) { update_socket_watch(TRUE); return FALSE; } static int send_msg( Loading @@ -60,10 +101,9 @@ send_msg( const void *msg, unsigned int length ) { int rv; VSCMsgHeader mhHeader; qemu_mutex_lock(&write_lock); qemu_mutex_lock(&socket_to_send_lock); if (verbose > 10) { printf("sending type=%d id=%u, len =%u (0x%x)\n", Loading @@ -73,23 +113,11 @@ send_msg( mhHeader.type = htonl(type); mhHeader.reader_id = 0; mhHeader.length = htonl(length); rv = write(sock, &mhHeader, sizeof(mhHeader)); if (rv < 0) { /* Error */ fprintf(stderr, "write header error\n"); close(sock); qemu_mutex_unlock(&write_lock); return 16; } rv = write(sock, msg, length); if (rv < 0) { /* Error */ fprintf(stderr, "write error\n"); close(sock); qemu_mutex_unlock(&write_lock); return 16; } qemu_mutex_unlock(&write_lock); g_byte_array_append(socket_to_send, (guint8 *)&mhHeader, sizeof(mhHeader)); g_byte_array_append(socket_to_send, (guint8 *)msg, length); g_idle_add(socket_prepare_sending, NULL); qemu_mutex_unlock(&socket_to_send_lock); return 0; } Loading Loading @@ -245,31 +273,52 @@ on_host_init(VSCMsgHeader *mhHeader, VSCMsgInit *incoming) return 0; } enum { STATE_HEADER, STATE_MESSAGE, }; #define APDUBufSize 270 static int do_socket_read(void) static gboolean do_socket_read(GIOChannel *source, GIOCondition condition, gpointer data) { int rv; int dwSendLength; int dwRecvLength; uint8_t pbRecvBuffer[APDUBufSize]; uint8_t pbSendBuffer[APDUBufSize]; static uint8_t pbSendBuffer[APDUBufSize]; VReaderStatus reader_status; VReader *reader = NULL; VSCMsgHeader mhHeader; static VSCMsgHeader mhHeader; VSCMsgError *error_msg; GError *err = NULL; rv = read(sock, &mhHeader, sizeof(mhHeader)); if (rv < sizeof(mhHeader)) { /* Error */ if (rv < 0) { perror("header read error\n"); } else { fprintf(stderr, "header short read %d\n", rv); 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); } return -1; 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); Loading @@ -283,20 +332,19 @@ do_socket_read(void) case VSC_Flush: case VSC_Error: case VSC_Init: rv = read(sock, pbSendBuffer, mhHeader.length); break; 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 -1; return FALSE; } } if (state == STATE_MESSAGE) { switch (mhHeader.type) { case VSC_APDU: if (rv < 0) { /* Error */ fprintf(stderr, "read error\n"); close(sock); return -1; } if (verbose) { printf(" recv APDU: "); print_byte_array(pbSendBuffer, mhHeader.length); Loading Loading @@ -355,29 +403,73 @@ do_socket_read(void) break; case VSC_Init: if (on_host_init(&mhHeader, (VSCMsgInit *)pbSendBuffer) < 0) { return -1; return FALSE; } break; default: printf("Default\n"); return -1; g_warn_if_reached(); return FALSE; } return 0; state = STATE_HEADER; } return TRUE; } static gboolean do_socket(GIOChannel *source, GIOCondition condition, gpointer data) { /* not sure if two watches work well with a single win32 sources */ if (condition & G_IO_OUT) { if (!do_socket_send(source, condition, data)) { return FALSE; } } if (condition & G_IO_IN) { if (!do_socket_read(source, condition, data)) { return FALSE; } } return TRUE; } static void do_command(void) update_socket_watch(gboolean out) { if (socket_tag != 0) { g_source_remove(socket_tag); } socket_tag = g_io_add_watch(channel_socket, G_IO_IN | (out ? G_IO_OUT : 0), do_socket, NULL); } static gboolean do_command(GIOChannel *source, GIOCondition condition, gpointer data) { char inbuf[255]; char *string; VCardEmulError error; static unsigned int default_reader_id; unsigned int reader_id; VReader *reader = NULL; GError *err = NULL; g_assert(condition & G_IO_IN); reader_id = default_reader_id; string = fgets(inbuf, sizeof(inbuf), stdin); g_io_channel_read_line(source, &string, NULL, NULL, &err); if (err != NULL) { g_error("Error while reading command: %s", err->message); } if (string != NULL) { if (strncmp(string, "exit", 4) == 0) { /* remove all the readers */ Loading Loading @@ -491,6 +583,8 @@ do_command(void) vreader_free(reader); printf("> "); fflush(stdout); return TRUE; } Loading @@ -504,7 +598,7 @@ connect_to_qemu( ) { struct addrinfo hints; struct addrinfo *server; int ret; int ret, sock; sock = qemu_socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) { Loading Loading @@ -543,6 +637,8 @@ main( int argc, char *argv[] ) { GMainLoop *loop; GIOChannel *channel_stdin; char *qemu_host; char *qemu_port; VSCMsgHeader mhHeader; Loading @@ -552,7 +648,10 @@ main( char *cert_names[MAX_CERTS]; char *emul_args = NULL; int cert_count = 0; int c, rv; int c, sock; if (socket_init() != 0) return 1; while ((c = getopt(argc, argv, "c:e:pd:")) != -1) { switch (c) { Loading Loading @@ -618,15 +717,33 @@ main( exit(5); } qemu_mutex_init(&write_lock); socket_to_send = g_byte_array_new(); qemu_mutex_init(&socket_to_send_lock); qemu_mutex_init(&pending_reader_lock); qemu_cond_init(&pending_reader_condition); vcard_emul_init(command_line_options); loop = g_main_loop_new(NULL, true); printf("> "); fflush(stdout); #ifdef _WIN32 channel_stdin = g_io_channel_win32_new_fd(STDIN_FILENO); #else channel_stdin = g_io_channel_unix_new(STDIN_FILENO); #endif g_io_add_watch(channel_stdin, G_IO_IN, do_command, NULL); #ifdef _WIN32 channel_socket = g_io_channel_win32_new_socket(sock); #else channel_socket = g_io_channel_unix_new(sock); #endif g_io_channel_set_encoding(channel_socket, NULL, NULL); /* we buffer ourself for thread safety reasons */ g_io_channel_set_buffered(channel_socket, FALSE); /* Send init message, Host responds (and then we send reader attachments) */ VSCMsgInit init = { .version = htonl(VSCARD_VERSION), Loading @@ -635,28 +752,12 @@ main( }; send_msg(VSC_Init, mhHeader.reader_id, &init, sizeof(init)); do { fd_set fds; FD_ZERO(&fds); FD_SET(1, &fds); FD_SET(sock, &fds); g_main_loop_run(loop); g_main_loop_unref(loop); /* waiting on input from the socket */ rv = select(sock+1, &fds, NULL, NULL, NULL); if (rv < 0) { /* handle error */ perror("select"); return 7; } if (FD_ISSET(1, &fds)) { do_command(); } if (!FD_ISSET(sock, &fds)) { continue; } rv = do_socket_read(); } while (rv >= 0); g_io_channel_unref(channel_stdin); g_io_channel_unref(channel_socket); g_byte_array_unref(socket_to_send); return 0; } Loading
libcacard/vscclient.c +246 −145 Original line number Diff line number Diff line Loading @@ -10,7 +10,10 @@ * See the COPYING.LIB file in the top-level directory. */ #ifndef _WIN32 #include <netdb.h> #endif #include <glib.h> #include "qemu-common.h" #include "qemu/thread.h" Loading @@ -22,9 +25,7 @@ #include "vcard_emul.h" #include "vevent.h" int verbose; int sock; static int verbose; static void print_byte_array( Loading @@ -51,7 +52,47 @@ print_usage(void) { vcard_emul_usage(); } static QemuMutex write_lock; static GIOChannel *channel_socket; static GByteArray *socket_to_send; static QemuMutex socket_to_send_lock; static guint socket_tag; static void update_socket_watch(gboolean out); static gboolean do_socket_send(GIOChannel *source, GIOCondition condition, gpointer data) { gsize bw; GError *err = NULL; g_return_val_if_fail(socket_to_send->len != 0, FALSE); g_return_val_if_fail(condition & G_IO_OUT, FALSE); g_io_channel_write_chars(channel_socket, (gchar *)socket_to_send->data, socket_to_send->len, &bw, &err); if (err != NULL) { g_error("Error while sending socket %s", err->message); return FALSE; } g_byte_array_remove_range(socket_to_send, 0, bw); if (socket_to_send->len == 0) { update_socket_watch(FALSE); return FALSE; } return TRUE; } static gboolean socket_prepare_sending(gpointer user_data) { update_socket_watch(TRUE); return FALSE; } static int send_msg( Loading @@ -60,10 +101,9 @@ send_msg( const void *msg, unsigned int length ) { int rv; VSCMsgHeader mhHeader; qemu_mutex_lock(&write_lock); qemu_mutex_lock(&socket_to_send_lock); if (verbose > 10) { printf("sending type=%d id=%u, len =%u (0x%x)\n", Loading @@ -73,23 +113,11 @@ send_msg( mhHeader.type = htonl(type); mhHeader.reader_id = 0; mhHeader.length = htonl(length); rv = write(sock, &mhHeader, sizeof(mhHeader)); if (rv < 0) { /* Error */ fprintf(stderr, "write header error\n"); close(sock); qemu_mutex_unlock(&write_lock); return 16; } rv = write(sock, msg, length); if (rv < 0) { /* Error */ fprintf(stderr, "write error\n"); close(sock); qemu_mutex_unlock(&write_lock); return 16; } qemu_mutex_unlock(&write_lock); g_byte_array_append(socket_to_send, (guint8 *)&mhHeader, sizeof(mhHeader)); g_byte_array_append(socket_to_send, (guint8 *)msg, length); g_idle_add(socket_prepare_sending, NULL); qemu_mutex_unlock(&socket_to_send_lock); return 0; } Loading Loading @@ -245,31 +273,52 @@ on_host_init(VSCMsgHeader *mhHeader, VSCMsgInit *incoming) return 0; } enum { STATE_HEADER, STATE_MESSAGE, }; #define APDUBufSize 270 static int do_socket_read(void) static gboolean do_socket_read(GIOChannel *source, GIOCondition condition, gpointer data) { int rv; int dwSendLength; int dwRecvLength; uint8_t pbRecvBuffer[APDUBufSize]; uint8_t pbSendBuffer[APDUBufSize]; static uint8_t pbSendBuffer[APDUBufSize]; VReaderStatus reader_status; VReader *reader = NULL; VSCMsgHeader mhHeader; static VSCMsgHeader mhHeader; VSCMsgError *error_msg; GError *err = NULL; rv = read(sock, &mhHeader, sizeof(mhHeader)); if (rv < sizeof(mhHeader)) { /* Error */ if (rv < 0) { perror("header read error\n"); } else { fprintf(stderr, "header short read %d\n", rv); 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); } return -1; 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); Loading @@ -283,20 +332,19 @@ do_socket_read(void) case VSC_Flush: case VSC_Error: case VSC_Init: rv = read(sock, pbSendBuffer, mhHeader.length); break; 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 -1; return FALSE; } } if (state == STATE_MESSAGE) { switch (mhHeader.type) { case VSC_APDU: if (rv < 0) { /* Error */ fprintf(stderr, "read error\n"); close(sock); return -1; } if (verbose) { printf(" recv APDU: "); print_byte_array(pbSendBuffer, mhHeader.length); Loading Loading @@ -355,29 +403,73 @@ do_socket_read(void) break; case VSC_Init: if (on_host_init(&mhHeader, (VSCMsgInit *)pbSendBuffer) < 0) { return -1; return FALSE; } break; default: printf("Default\n"); return -1; g_warn_if_reached(); return FALSE; } return 0; state = STATE_HEADER; } return TRUE; } static gboolean do_socket(GIOChannel *source, GIOCondition condition, gpointer data) { /* not sure if two watches work well with a single win32 sources */ if (condition & G_IO_OUT) { if (!do_socket_send(source, condition, data)) { return FALSE; } } if (condition & G_IO_IN) { if (!do_socket_read(source, condition, data)) { return FALSE; } } return TRUE; } static void do_command(void) update_socket_watch(gboolean out) { if (socket_tag != 0) { g_source_remove(socket_tag); } socket_tag = g_io_add_watch(channel_socket, G_IO_IN | (out ? G_IO_OUT : 0), do_socket, NULL); } static gboolean do_command(GIOChannel *source, GIOCondition condition, gpointer data) { char inbuf[255]; char *string; VCardEmulError error; static unsigned int default_reader_id; unsigned int reader_id; VReader *reader = NULL; GError *err = NULL; g_assert(condition & G_IO_IN); reader_id = default_reader_id; string = fgets(inbuf, sizeof(inbuf), stdin); g_io_channel_read_line(source, &string, NULL, NULL, &err); if (err != NULL) { g_error("Error while reading command: %s", err->message); } if (string != NULL) { if (strncmp(string, "exit", 4) == 0) { /* remove all the readers */ Loading Loading @@ -491,6 +583,8 @@ do_command(void) vreader_free(reader); printf("> "); fflush(stdout); return TRUE; } Loading @@ -504,7 +598,7 @@ connect_to_qemu( ) { struct addrinfo hints; struct addrinfo *server; int ret; int ret, sock; sock = qemu_socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) { Loading Loading @@ -543,6 +637,8 @@ main( int argc, char *argv[] ) { GMainLoop *loop; GIOChannel *channel_stdin; char *qemu_host; char *qemu_port; VSCMsgHeader mhHeader; Loading @@ -552,7 +648,10 @@ main( char *cert_names[MAX_CERTS]; char *emul_args = NULL; int cert_count = 0; int c, rv; int c, sock; if (socket_init() != 0) return 1; while ((c = getopt(argc, argv, "c:e:pd:")) != -1) { switch (c) { Loading Loading @@ -618,15 +717,33 @@ main( exit(5); } qemu_mutex_init(&write_lock); socket_to_send = g_byte_array_new(); qemu_mutex_init(&socket_to_send_lock); qemu_mutex_init(&pending_reader_lock); qemu_cond_init(&pending_reader_condition); vcard_emul_init(command_line_options); loop = g_main_loop_new(NULL, true); printf("> "); fflush(stdout); #ifdef _WIN32 channel_stdin = g_io_channel_win32_new_fd(STDIN_FILENO); #else channel_stdin = g_io_channel_unix_new(STDIN_FILENO); #endif g_io_add_watch(channel_stdin, G_IO_IN, do_command, NULL); #ifdef _WIN32 channel_socket = g_io_channel_win32_new_socket(sock); #else channel_socket = g_io_channel_unix_new(sock); #endif g_io_channel_set_encoding(channel_socket, NULL, NULL); /* we buffer ourself for thread safety reasons */ g_io_channel_set_buffered(channel_socket, FALSE); /* Send init message, Host responds (and then we send reader attachments) */ VSCMsgInit init = { .version = htonl(VSCARD_VERSION), Loading @@ -635,28 +752,12 @@ main( }; send_msg(VSC_Init, mhHeader.reader_id, &init, sizeof(init)); do { fd_set fds; FD_ZERO(&fds); FD_SET(1, &fds); FD_SET(sock, &fds); g_main_loop_run(loop); g_main_loop_unref(loop); /* waiting on input from the socket */ rv = select(sock+1, &fds, NULL, NULL, NULL); if (rv < 0) { /* handle error */ perror("select"); return 7; } if (FD_ISSET(1, &fds)) { do_command(); } if (!FD_ISSET(sock, &fds)) { continue; } rv = do_socket_read(); } while (rv >= 0); g_io_channel_unref(channel_stdin); g_io_channel_unref(channel_socket); g_byte_array_unref(socket_to_send); return 0; }