1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-11-10 21:38:50 +01:00

scd: Only submit apdu_get_status when needed.

* scd/apdu.c (apdu_dev_list_finish): Return Boolean value if
all device support INTERRUPT transfer.
* scd/ccid-driver.c (ccid_dev_scan_finish): Likewise.
* scd/app.c (app_new_register): Fix initial value of card_status.
(select_application): Call update_fdset_for_usb.
(scd_update_reader_status_file): Ditto.
* scd/scdaemon.c (update_fdset_for_usb, need_tick): New.
(handle_connections): Call handle_tick when select returns.
Let select watch USB file descriptors, too.
Call libusb_handle_events_timeout_completed for INTERRUPT transfer.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
This commit is contained in:
NIIBE Yutaka 2017-01-26 22:02:41 +09:00
parent 9b06633c81
commit 881dcdfd84
7 changed files with 145 additions and 42 deletions

View File

@ -2970,15 +2970,22 @@ apdu_dev_list_start (const char *portstr, struct dev_list **l_p)
return 0; return 0;
} }
void int
apdu_dev_list_finish (struct dev_list *dl) apdu_dev_list_finish (struct dev_list *dl)
{ {
int all_have_intr_endp;
#ifdef HAVE_LIBUSB #ifdef HAVE_LIBUSB
if (dl->ccid_table) if (dl->ccid_table)
ccid_dev_scan_finish (dl->ccid_table, dl->idx_max); all_have_intr_endp = ccid_dev_scan_finish (dl->ccid_table, dl->idx_max);
else
all_have_intr_endp = 0;
#else
all_have_intr_endp = 0;
#endif #endif
xfree (dl); xfree (dl);
npth_mutex_unlock (&reader_table_lock); npth_mutex_unlock (&reader_table_lock);
return all_have_intr_endp;
} }

View File

@ -88,7 +88,7 @@ struct dev_list;
gpg_error_t apdu_init (void); gpg_error_t apdu_init (void);
gpg_error_t apdu_dev_list_start (const char *portstr, struct dev_list **l_p); gpg_error_t apdu_dev_list_start (const char *portstr, struct dev_list **l_p);
void apdu_dev_list_finish (struct dev_list *l); int apdu_dev_list_finish (struct dev_list *l);
/* Note, that apdu_open_reader returns no status word but -1 on error. */ /* Note, that apdu_open_reader returns no status word but -1 on error. */
int apdu_open_reader (struct dev_list *l); int apdu_open_reader (struct dev_list *l);

View File

@ -192,6 +192,7 @@ app_new_register (int slot, ctrl_t ctrl, const char *name)
} }
app->slot = slot; app->slot = slot;
app->card_status = (unsigned int)-1;
if (npth_mutex_init (&app->lock, NULL)) if (npth_mutex_init (&app->lock, NULL))
{ {
@ -329,6 +330,7 @@ select_application (ctrl_t ctrl, const char *name, app_t *r_app,
if (scan || !app_top) if (scan || !app_top)
{ {
struct dev_list *l; struct dev_list *l;
int all_have_intr_endp;
err = apdu_dev_list_start (opt.reader_port, &l); err = apdu_dev_list_start (opt.reader_port, &l);
if (err) if (err)
@ -368,7 +370,8 @@ select_application (ctrl_t ctrl, const char *name, app_t *r_app,
} }
} }
apdu_dev_list_finish (l); all_have_intr_endp = apdu_dev_list_finish (l);
update_fdset_for_usb (1, all_have_intr_endp);
} }
npth_mutex_lock (&app_list_lock); npth_mutex_lock (&app_list_lock);
@ -1050,6 +1053,7 @@ scd_update_reader_status_file (void)
log_debug ("Removal of a card: %d\n", a->slot); log_debug ("Removal of a card: %d\n", a->slot);
apdu_close_reader (a->slot); apdu_close_reader (a->slot);
deallocate_app (a); deallocate_app (a);
update_fdset_for_usb (0, 0);
} }
else else
a->card_status = status; a->card_status = status;

View File

@ -1699,13 +1699,17 @@ ccid_dev_scan (int *idx_max_p, struct ccid_dev_table **t_p)
return err; return err;
} }
void int
ccid_dev_scan_finish (struct ccid_dev_table *tbl, int max) ccid_dev_scan_finish (struct ccid_dev_table *tbl, int max)
{ {
int all_have_intr_endp = 1;
int i; int i;
for (i = 0; i < max; i++) for (i = 0; i < max; i++)
{ {
if (tbl[i].ep_intr == -1)
all_have_intr_endp = 0;
free (tbl[i].ifcdesc_extra); free (tbl[i].ifcdesc_extra);
tbl[i].transport = 0; tbl[i].transport = 0;
tbl[i].n = 0; tbl[i].n = 0;
@ -1719,6 +1723,8 @@ ccid_dev_scan_finish (struct ccid_dev_table *tbl, int max)
} }
libusb_free_device_list (ccid_usb_dev_list, 1); libusb_free_device_list (ccid_usb_dev_list, 1);
ccid_usb_dev_list = NULL; ccid_usb_dev_list = NULL;
return all_have_intr_endp;
} }
unsigned int unsigned int

View File

@ -115,7 +115,7 @@ int ccid_set_debug_level (int level);
char *ccid_get_reader_list (void); char *ccid_get_reader_list (void);
gpg_error_t ccid_dev_scan (int *idx_max, struct ccid_dev_table **t_p); gpg_error_t ccid_dev_scan (int *idx_max, struct ccid_dev_table **t_p);
void ccid_dev_scan_finish (struct ccid_dev_table *tbl, int max); int ccid_dev_scan_finish (struct ccid_dev_table *tbl, int max);
unsigned int ccid_get_BAI (int, struct ccid_dev_table *tbl); unsigned int ccid_get_BAI (int, struct ccid_dev_table *tbl);
int ccid_compare_BAI (ccid_driver_t handle, unsigned int); int ccid_compare_BAI (ccid_driver_t handle, unsigned int);
int ccid_open_reader (const char *spec_reader_name, int ccid_open_reader (const char *spec_reader_name,

View File

@ -44,6 +44,10 @@
#include <assuan.h> /* malloc hooks */ #include <assuan.h> /* malloc hooks */
#ifdef HAVE_LIBUSB
#include <libusb.h>
#endif
#include "i18n.h" #include "i18n.h"
#include "sysutils.h" #include "sysutils.h"
#include "app-common.h" #include "app-common.h"
@ -224,7 +228,17 @@ static assuan_sock_nonce_t socket_nonce;
disabled but it won't perform any ticker specific actions. */ disabled but it won't perform any ticker specific actions. */
static int ticker_disabled; static int ticker_disabled;
/* Set of FD to select. */
static fd_set fdset;
/* Max FD to select. */
static int nfd;
/* Set if all usb devices have INTERRUPT endpoints. */
static int usb_all_have_intr_endp;
/* FD to listen incomming connections. */
static int listen_fd;
static char *create_socket_name (char *standard_name); static char *create_socket_name (char *standard_name);
static gnupg_fd_t create_server_socket (const char *name, static gnupg_fd_t create_server_socket (const char *name,
@ -232,7 +246,7 @@ static gnupg_fd_t create_server_socket (const char *name,
assuan_sock_nonce_t *nonce); assuan_sock_nonce_t *nonce);
static void *start_connection_thread (void *arg); static void *start_connection_thread (void *arg);
static void handle_connections (int listen_fd); static void handle_connections (void);
/* Pth wrapper function definitions. */ /* Pth wrapper function definitions. */
ASSUAN_SYSTEM_NPTH_IMPL; ASSUAN_SYSTEM_NPTH_IMPL;
@ -780,7 +794,8 @@ main (int argc, char **argv )
/* We run handle_connection to wait for the shutdown signal and /* We run handle_connection to wait for the shutdown signal and
to run the ticker stuff. */ to run the ticker stuff. */
handle_connections (fd); listen_fd = fd;
handle_connections ();
if (fd != -1) if (fd != -1)
close (fd); close (fd);
} }
@ -912,7 +927,8 @@ main (int argc, char **argv )
#endif /*!HAVE_W32_SYSTEM*/ #endif /*!HAVE_W32_SYSTEM*/
handle_connections (fd); listen_fd = fd;
handle_connections ();
close (fd); close (fd);
} }
@ -1181,23 +1197,76 @@ start_connection_thread (void *arg)
} }
void
update_fdset_for_usb (int scanned, int all_have_intr_endp)
{
#ifdef HAVE_LIBUSB
const struct libusb_pollfd **pfd_array = libusb_get_pollfds (NULL);
const struct libusb_pollfd **p;
#endif
if (scanned)
usb_all_have_intr_endp = all_have_intr_endp;
FD_ZERO (&fdset);
nfd = 0;
if (listen_fd != -1)
{
FD_SET (listen_fd, &fdset);
nfd = listen_fd;
}
#ifdef HAVE_LIBUSB
for (p = pfd_array; *p; p++)
{
int fd = (*p)->fd;
FD_SET (fd, &fdset);
if (nfd < fd)
nfd = fd;
p++;
}
libusb_free_pollfds (pfd_array);
#endif
log_debug ("update_fdset_for_usb (%d, %d): %d\n",
scanned, all_have_intr_endp, nfd);
}
static int
need_tick (void)
{
if (shutdown_pending)
return 1;
if (listen_fd != -1 && nfd == listen_fd)
return 1;
if (usb_all_have_intr_endp)
return 0;
return 1;
}
/* Connection handler loop. Wait for connection requests and spawn a /* Connection handler loop. Wait for connection requests and spawn a
thread after accepting a connection. LISTEN_FD is allowed to be -1 thread after accepting a connection. LISTEN_FD is allowed to be -1
in which case this code will only do regular timeouts and handle in which case this code will only do regular timeouts and handle
signals. */ signals. */
static void static void
handle_connections (int listen_fd) handle_connections (void)
{ {
npth_attr_t tattr; npth_attr_t tattr;
struct sockaddr_un paddr; struct sockaddr_un paddr;
socklen_t plen; socklen_t plen;
fd_set fdset, read_fdset; fd_set read_fdset;
int ret; int ret;
int fd; int fd;
int nfd;
struct timespec abstime; struct timespec abstime;
struct timespec curtime; struct timespec curtime;
struct timespec timeout; struct timespec timeout;
struct timespec *t;
int saved_errno; int saved_errno;
#ifndef HAVE_W32_SYSTEM #ifndef HAVE_W32_SYSTEM
int signo; int signo;
@ -1244,56 +1313,63 @@ handle_connections (int listen_fd)
used to just wait on a signal or timeout event. */ used to just wait on a signal or timeout event. */
FD_ZERO (&fdset); FD_ZERO (&fdset);
listen_fd = -1; listen_fd = -1;
} }
npth_clock_gettime (&curtime); if (need_tick ())
if (!(npth_timercmp (&curtime, &abstime, <))) {
{ npth_clock_gettime (&curtime);
/* Timeout. */ if (!(npth_timercmp (&curtime, &abstime, <)))
handle_tick (); {
timeout.tv_sec = TIMERTICK_INTERVAL_SEC; /* Timeout. */
timeout.tv_nsec = TIMERTICK_INTERVAL_USEC * 1000; timeout.tv_sec = TIMERTICK_INTERVAL_SEC;
npth_timeradd (&curtime, &timeout, &abstime); timeout.tv_nsec = TIMERTICK_INTERVAL_USEC * 1000;
} npth_timeradd (&curtime, &timeout, &abstime);
npth_timersub (&abstime, &curtime, &timeout); }
npth_timersub (&abstime, &curtime, &timeout);
t = &timeout;
}
else
t = NULL;
handle_tick ();
/* POSIX says that fd_set should be implemented as a structure, /* POSIX says that fd_set should be implemented as a structure,
thus a simple assignment is fine to copy the entire set. */ thus a simple assignment is fine to copy the entire set. */
read_fdset = fdset; read_fdset = fdset;
#ifndef HAVE_W32_SYSTEM #ifndef HAVE_W32_SYSTEM
ret = npth_pselect (nfd+1, &read_fdset, NULL, NULL, &timeout, npth_sigev_sigmask()); ret = npth_pselect (nfd+1, &read_fdset, NULL, NULL, t, npth_sigev_sigmask());
saved_errno = errno; saved_errno = errno;
while (npth_sigev_get_pending(&signo)) while (npth_sigev_get_pending(&signo))
handle_signal (signo); handle_signal (signo);
#else #else
ret = npth_eselect (nfd+1, &read_fdset, NULL, NULL, &timeout, NULL, NULL); ret = npth_eselect (nfd+1, &read_fdset, NULL, NULL, t, NULL, NULL);
saved_errno = errno; saved_errno = errno;
#endif #endif
if (ret == -1 && saved_errno != EINTR) if (ret == -1 && saved_errno != EINTR)
{ {
log_error (_("npth_pselect failed: %s - waiting 1s\n"), log_error (_("npth_pselect failed: %s - waiting 1s\n"),
strerror (saved_errno)); strerror (saved_errno));
npth_sleep (1); npth_sleep (1);
continue; continue;
} }
if (ret <= 0) if (ret <= 0)
/* Timeout. Will be handled when calculating the next timeout. */ /* Timeout. Will be handled when calculating the next timeout. */
continue; continue;
if (listen_fd != -1 && FD_ISSET (listen_fd, &read_fdset)) if (listen_fd != -1 && FD_ISSET (listen_fd, &read_fdset))
{ {
ctrl_t ctrl; ctrl_t ctrl;
plen = sizeof paddr; plen = sizeof paddr;
fd = npth_accept (listen_fd, (struct sockaddr *)&paddr, &plen); fd = npth_accept (listen_fd, (struct sockaddr *)&paddr, &plen);
if (fd == -1) if (fd == -1)
{ {
log_error ("accept failed: %s\n", strerror (errno)); log_error ("accept failed: %s\n", strerror (errno));
} }
else if ( !(ctrl = xtrycalloc (1, sizeof *ctrl)) ) else if ( !(ctrl = xtrycalloc (1, sizeof *ctrl)) )
{ {
log_error ("error allocating connection control data: %s\n", log_error ("error allocating connection control data: %s\n",
@ -1303,12 +1379,12 @@ handle_connections (int listen_fd)
else else
{ {
char threadname[50]; char threadname[50];
npth_t thread; npth_t thread;
snprintf (threadname, sizeof threadname, "conn fd=%d", fd); snprintf (threadname, sizeof threadname, "conn fd=%d", fd);
ctrl->thread_startup.fd = INT2FD (fd); ctrl->thread_startup.fd = INT2FD (fd);
ret = npth_create (&thread, &tattr, start_connection_thread, ctrl); ret = npth_create (&thread, &tattr, start_connection_thread, ctrl);
if (ret) if (ret)
{ {
log_error ("error spawning connection handler: %s\n", log_error ("error spawning connection handler: %s\n",
strerror (ret)); strerror (ret));
@ -1316,10 +1392,19 @@ handle_connections (int listen_fd)
close (fd); close (fd);
} }
else else
npth_setname_np (thread, threadname); npth_setname_np (thread, threadname);
} }
fd = -1;
} ret--;
}
#ifdef HAVE_LIBUSB
if (ret)
{
struct timeval tv = {0, 0};
libusb_handle_events_timeout_completed (NULL, &tv, NULL);
}
#endif
} }
cleanup (); cleanup ();

View File

@ -125,6 +125,7 @@ void send_status_info (ctrl_t ctrl, const char *keyword, ...)
void send_status_direct (ctrl_t ctrl, const char *keyword, const char *args); void send_status_direct (ctrl_t ctrl, const char *keyword, const char *args);
void scd_update_reader_status_file (void); void scd_update_reader_status_file (void);
void send_client_notifications (app_t app, int removal); void send_client_notifications (app_t app, int removal);
void update_fdset_for_usb (int scanned, int all_have_intr_endp);
#endif /*SCDAEMON_H*/ #endif /*SCDAEMON_H*/