[Pcsclite-cvs-commit] r4434 - in /trunk/PCSC/src: eventhandler.c pcscd.h.in pcscdaemon.c readerfactory.c winscard.c winscard_clnt.c winscard_msg.c winscard_msg.h winscard_msg_srv.c winscard_svc.c

rousseau at users.alioth.debian.org rousseau at users.alioth.debian.org
Tue Oct 6 09:37:51 UTC 2009


Author: rousseau
Date: Tue Oct  6 09:37:51 2009
New Revision: 4434

URL: http://svn.debian.org/wsvn/pcsclite/?sc=1&rev=4434
Log:
redesign the client/server communication:
- no more shared memory used (allow pcscd and libpcsclite1.so to be on
  different computer and talk over a network)
- no more difference between short and extended APDU
- no more use of a /var/run/pcscd/pcscd.events/ directory. events are
  sent through the socket
- simpler command format between client and server

The side effect is that you are not able to mix an old pcscd with a new
libpcsclite1.so or the reverse. SCardEstablishContext() will fail unless
you update both sides of the communication.

Modified:
    trunk/PCSC/src/eventhandler.c
    trunk/PCSC/src/pcscd.h.in
    trunk/PCSC/src/pcscdaemon.c
    trunk/PCSC/src/readerfactory.c
    trunk/PCSC/src/winscard.c
    trunk/PCSC/src/winscard_clnt.c
    trunk/PCSC/src/winscard_msg.c
    trunk/PCSC/src/winscard_msg.h
    trunk/PCSC/src/winscard_msg_srv.c
    trunk/PCSC/src/winscard_svc.c

Modified: trunk/PCSC/src/eventhandler.c
URL: http://svn.debian.org/wsvn/pcsclite/trunk/PCSC/src/eventhandler.c?rev=4434&op=diff
==============================================================================
--- trunk/PCSC/src/eventhandler.c (original)
+++ trunk/PCSC/src/eventhandler.c Tue Oct  6 09:37:51 2009
@@ -39,7 +39,7 @@
 #include "winscard_svc.h"
 #include "simclist.h"
 
-static PREADER_STATE readerStates[PCSCLITE_MAX_READERS_CONTEXTS];
+READER_STATE readerStates[PCSCLITE_MAX_READERS_CONTEXTS];
 static list_t ClientsWaitingForEvent;	/**< list of client file descriptors */
 PCSCLITE_MUTEX_T ClientsWaitingForEvent_lock;	/**< lock for the above list */
 
@@ -104,59 +104,29 @@
 
 LONG EHInitializeEventStructures(void)
 {
-	int fd, i, pageSize;
-	int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
-
-	fd = 0;
-	i = 0;
-	pageSize = 0;
-
-	(void)SYS_RemoveFile(PCSCLITE_PUBSHM_FILE);
-
-	fd = SYS_OpenFile(PCSCLITE_PUBSHM_FILE, O_RDWR | O_CREAT, mode);
-	if (fd < 0)
-	{
-		Log3(PCSC_LOG_CRITICAL, "Cannot create public shared file %s: %s",
-			PCSCLITE_PUBSHM_FILE, strerror(errno));
-		exit(1);
-	}
-
-	/* set correct mode even is umask is too restictive */
-	(void)SYS_Chmod(PCSCLITE_PUBSHM_FILE, mode);
-
-	pageSize = SYS_GetPageSize();
-
-	/*
-	 * Jump to end of file space and allocate zero's
-	 */
-	(void)SYS_SeekFile(fd, pageSize * PCSCLITE_MAX_READERS_CONTEXTS);
-	(void)SYS_WriteFile(fd, "", 1);
-
-	/*
-	 * Allocate each reader structure
-	 */
+	int i;
+
 	for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
 	{
-		readerStates[i] = (PREADER_STATE)
-			SYS_MemoryMap(sizeof(READER_STATE), fd, (i * pageSize));
-		if (readerStates[i] == MAP_FAILED)
-		{
-			Log3(PCSC_LOG_CRITICAL, "Cannot memory map public shared file %s: %s",
-				PCSCLITE_PUBSHM_FILE, strerror(errno));
-			exit(1);
-		}
-
-		/*
-		 * Zero out each value in the struct
-		 */
-		memset((readerStates[i])->readerName, 0, MAX_READERNAME);
-		memset((readerStates[i])->cardAtr, 0, MAX_ATR_SIZE);
-		(readerStates[i])->readerID = 0;
-		(readerStates[i])->readerState = 0;
-		(readerStates[i])->readerSharing = 0;
-		(readerStates[i])->cardAtrLength = 0;
-		(readerStates[i])->cardProtocol = SCARD_PROTOCOL_UNDEFINED;
-	}
+		/* Zero out each value in the struct */
+		memset(readerStates[i].readerName, 0, MAX_READERNAME);
+		memset(readerStates[i].cardAtr, 0, MAX_ATR_SIZE);
+		readerStates[i].readerID = 0;
+		readerStates[i].readerState = 0;
+		readerStates[i].readerSharing = 0;
+		readerStates[i].cardAtrLength = 0;
+		readerStates[i].cardProtocol = SCARD_PROTOCOL_UNDEFINED;
+	}
+
+	list_init(&ClientsWaitingForEvent);
+
+	/* request to store copies, and provide the metric function */
+    list_attributes_copy(&ClientsWaitingForEvent, list_meter_int32_t, 1);
+
+	/* setting the comparator, so the list can sort, find the min, max etc */
+    list_attributes_comparator(&ClientsWaitingForEvent, list_comparator_int32_t);
+
+	SYS_MutexInit(ClientsWaitingForEvent_lock);
 
 	return SCARD_S_SUCCESS;
 }
@@ -247,7 +217,7 @@
 	 */
 	for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
 	{
-		if ((readerStates[i])->readerID == 0)
+		if (readerStates[i].readerID == 0)
 			break;
 	}
 
@@ -257,7 +227,7 @@
 	/*
 	 * Set all the attributes to this reader
 	 */
-	rContext->readerState = readerStates[i];
+	rContext->readerState = &readerStates[i];
 	(void)strlcpy(rContext->readerState->readerName, rContext->lpcReader,
 		sizeof(rContext->readerState->readerName));
 	memcpy(rContext->readerState->cardAtr, ucAtr, dwAtrLen);
@@ -377,7 +347,7 @@
 	rContext->readerState->readerSharing = dwReaderSharing =
 		rContext->dwContexts;
 
-	(void)StatSynchronize(rContext->readerState);
+	(void)EHSignalEventToClients();
 
 	while (1)
 	{
@@ -408,7 +378,7 @@
 
 			dwCurrentState = SCARD_UNKNOWN;
 
-			(void)StatSynchronize(rContext->readerState);
+			(void)EHSignalEventToClients();
 		}
 
 		if (dwStatus & SCARD_ABSENT)
@@ -438,7 +408,7 @@
 
 				incrementEventCounter(rContext->readerState);
 
-				(void)StatSynchronize(rContext->readerState);
+				(void)EHSignalEventToClients();
 			}
 
 		}
@@ -485,7 +455,7 @@
 
 				incrementEventCounter(rContext->readerState);
 
-				(void)StatSynchronize(rContext->readerState);
+				(void)EHSignalEventToClients();
 
 				Log2(PCSC_LOG_INFO, "Card inserted into %s", lpcReader);
 
@@ -512,7 +482,7 @@
 		{
 			dwReaderSharing = rContext->dwContexts;
 			rContext->readerState->readerSharing = dwReaderSharing;
-			(void)StatSynchronize(rContext->readerState);
+			(void)EHSignalEventToClients();
 		}
 
 		if (rContext->pthCardEvent)
@@ -531,7 +501,7 @@
 			/*
 			 * Exit and notify the caller
 			 */
-			(void)StatSynchronize(rContext->readerState);
+			(void)EHSignalEventToClients();
 			Log1(PCSC_LOG_INFO, "Die");
 			rContext->dwLockId = 0;
 			(void)SYS_ThreadExit(NULL);

Modified: trunk/PCSC/src/pcscd.h.in
URL: http://svn.debian.org/wsvn/pcsclite/trunk/PCSC/src/pcscd.h.in?rev=4434&op=diff
==============================================================================
--- trunk/PCSC/src/pcscd.h.in (original)
+++ trunk/PCSC/src/pcscd.h.in Tue Oct  6 09:37:51 2009
@@ -30,19 +30,13 @@
 #define PCSCLITE_RUN_PID		PCSCLITE_IPC_DIR "/pcscd.pid"
 
 #define PCSCLITE_READER_CONFIG		PCSCLITE_CONFIG_DIR "/reader.conf"
-#define PCSCLITE_PUBSHM_FILE		PCSCLITE_IPC_DIR "/pcscd.pub"
 #define PCSCLITE_CSOCK_NAME		PCSCLITE_IPC_DIR "/pcscd.comm"
-#define PCSCLITE_EVENTS_DIR		PCSCLITE_IPC_DIR "/pcscd.events"
 
 #define PCSCLITE_SVC_IDENTITY		0x01030000	/**< Service ID */
-
-#define PCSCLITE_INFINITE_TIMEOUT	4320000		/**< 50 day infinite t/o */
 
 #define PCSCLITE_VERSION_NUMBER		"@VERSION@"	/**< Current version */
 #define PCSCLITE_WRITE_TIMEOUT	1000			/**< write timeout */
 #define PCSCLITE_READ_TIMEOUT	120*1000		/**< read timeout */
-#define PCSCLITE_CLIENT_ATTEMPTS	120		/**< Attempts to reach sv */
-#define PCSCLITE_MCLIENT_ATTEMPTS	20		/**< Attempts to reach sv */
 #define PCSCLITE_STATUS_POLL_RATE	400000		/**< Status polling rate */
 #define PCSCLITE_LOCK_POLL_RATE		100000		/**< Lock polling rate */
 
@@ -62,14 +56,7 @@
 #define MAX_LIBNAME			100
 #define MAX_DEVICENAME		255
 
-/*
- * The message and buffer sizes must be multiples of 16.
- * The max message size must be at least large enough
- * to accomodate the transmit_struct
- */
-#define PCSCLITE_MAX_MESSAGE_SIZE	2048	/**< Transport msg len */
-#define MAX_BUFFER_SIZE			264	/**< Maximum Tx/Rx Buffer for short APDU */
-#define MAX_BUFFER_SIZE_EXTENDED	(4 + 3 + (1<<16) + 3)	/**< enhanced (64K + APDU + Lc + Le) Tx/Rx Buffer */
-#define PCSCLITE_SERVER_ATTEMPTS	5	/**< Attempts to reach cl */
+#define MAX_BUFFER_SIZE			264	/**< Maximum Tx/Rx Buffer for get/set attributes */
+#define MAX_BUFFER_SIZE_EXTENDED	(4 + 3 + (1<<16) + 3)	/**< max APDU (64K + APDU + Lc + Le) Tx/Rx Buffer */
 
 #endif

Modified: trunk/PCSC/src/pcscdaemon.c
URL: http://svn.debian.org/wsvn/pcsclite/trunk/PCSC/src/pcscdaemon.c?rev=4434&op=diff
==============================================================================
--- trunk/PCSC/src/pcscdaemon.c (original)
+++ trunk/PCSC/src/pcscdaemon.c Tue Oct  6 09:37:51 2009
@@ -305,10 +305,10 @@
 	}
 
 	/*
-	 * test the presence of /var/run/pcscd/pcsc.pub
-	 */
-
-	rv = SYS_Stat(PCSCLITE_PUBSHM_FILE, &fStatBuf);
+	 * test the presence of /var/run/pcscd/pcscd.comm
+	 */
+
+	rv = SYS_Stat(PCSCLITE_CSOCK_NAME, &fStatBuf);
 
 	if (rv == 0)
 	{
@@ -327,7 +327,7 @@
 			if (kill(pid, 0) == 0)
 			{
 				Log1(PCSC_LOG_CRITICAL,
-					"file " PCSCLITE_PUBSHM_FILE " already exists.");
+					"file " PCSCLITE_CSOCK_NAME " already exists.");
 				Log2(PCSC_LOG_CRITICAL,
 					"Another pcscd (pid: %d) seems to be running.", pid);
 				return EXIT_FAILURE;
@@ -346,13 +346,12 @@
 			}
 
 			Log1(PCSC_LOG_CRITICAL,
-				"file " PCSCLITE_PUBSHM_FILE " already exists.");
+				"file " PCSCLITE_CSOCK_NAME " already exists.");
 			Log1(PCSC_LOG_CRITICAL,
 				"Maybe another pcscd is running?");
 			Log1(PCSC_LOG_CRITICAL,
 				"I can't read process pid from " PCSCLITE_RUN_PID);
-			Log1(PCSC_LOG_CRITICAL,
-				"Remove " PCSCLITE_PUBSHM_FILE " and " PCSCLITE_CSOCK_NAME);
+			Log1(PCSC_LOG_CRITICAL, "Remove " PCSCLITE_CSOCK_NAME);
 			Log1(PCSC_LOG_CRITICAL,
 				"if pcscd is not running to clear this message.");
 			return EXIT_FAILURE;
@@ -429,25 +428,6 @@
 		else
 			Log2(PCSC_LOG_CRITICAL, "cannot create " PCSCLITE_RUN_PID ": %s",
 				strerror(errno));
-	}
-
-	/*
-	 * If PCSCLITE_EVENTS does not exist then create it
-	 */
-	rv = SYS_Stat(PCSCLITE_EVENTS_DIR, &fStatBuf);
-	if (rv < 0)
-	{
-		/* 1733 : world writable + sticky bit */
-		int mode = S_IRWXU | S_IWGRP | S_IXGRP | S_IWOTH | S_IXOTH | S_ISVTX;
-
-		rv = SYS_Mkdir(PCSCLITE_EVENTS_DIR, mode);
-		if (rv != 0)
-		{
-			Log2(PCSC_LOG_CRITICAL,
-				"cannot create " PCSCLITE_EVENTS_DIR ": %s", strerror(errno));
-			return EXIT_FAILURE;
-		}
-		(void)SYS_Chmod(PCSCLITE_EVENTS_DIR, mode);
 	}
 
 	/* cleanly remove /var/run/pcscd/pcsc.* files when exiting */
@@ -540,11 +520,6 @@
 {
 	int rv;
 
-	rv = SYS_RemoveFile(PCSCLITE_PUBSHM_FILE);
-	if (rv != 0)
-		Log2(PCSC_LOG_ERROR, "Cannot remove " PCSCLITE_PUBSHM_FILE ": %s",
-			strerror(errno));
-
 	rv = SYS_RemoveFile(PCSCLITE_CSOCK_NAME);
 	if (rv != 0)
 		Log2(PCSC_LOG_ERROR, "Cannot remove " PCSCLITE_CSOCK_NAME ": %s",
@@ -553,13 +528,6 @@
 	rv = SYS_RemoveFile(PCSCLITE_RUN_PID);
 	if (rv != 0)
 		Log2(PCSC_LOG_ERROR, "Cannot remove " PCSCLITE_RUN_PID ": %s",
-			strerror(errno));
-
-	(void)StatSynchronize(NULL);
-	SYS_Sleep(1);
-	rv = SYS_RemoveFile(PCSCLITE_EVENTS_DIR);
-	if (rv != 0)
-		Log2(PCSC_LOG_ERROR, "Cannot remove " PCSCLITE_EVENTS_DIR ": %s",
 			strerror(errno));
 }
 

Modified: trunk/PCSC/src/readerfactory.c
URL: http://svn.debian.org/wsvn/pcsclite/trunk/PCSC/src/readerfactory.c?rev=4434&op=diff
==============================================================================
--- trunk/PCSC/src/readerfactory.c (original)
+++ trunk/PCSC/src/readerfactory.c Tue Oct  6 09:37:51 2009
@@ -470,7 +470,7 @@
 		dwNumReadersContexts -= 1;
 
 		/* signal an event to clients */
-		StatSynchronize(NULL);
+		(void)EHSignalEventToClients();
 	}
 
 	return SCARD_S_SUCCESS;

Modified: trunk/PCSC/src/winscard.c
URL: http://svn.debian.org/wsvn/pcsclite/trunk/PCSC/src/winscard.c?rev=4434&op=diff
==============================================================================
--- trunk/PCSC/src/winscard.c (original)
+++ trunk/PCSC/src/winscard.c Tue Oct  6 09:37:51 2009
@@ -499,10 +499,9 @@
 	}
 
 	/*
-	 * Propagate new state to Shared Memory
+	 * Propagate new state to reader state
 	 */
 	rContext->readerState->readerSharing = rContext->dwContexts;
-	(void)StatSynchronize(rContext->readerState);
 
 	PROFILE_END
 
@@ -812,10 +811,9 @@
 	(void)RFClearReaderEventState(rContext, hCard);
 
 	/*
-	 * Propagate new state to Shared Memory
+	 * Propagate new state to reader state
 	 */
 	rContext->readerState->readerSharing = rContext->dwContexts;
-	(void)StatSynchronize(rContext->readerState);
 
 	return SCARD_S_SUCCESS;
 }
@@ -995,10 +993,9 @@
 	}
 
 	/*
-	 * Propagate new state to Shared Memory
+	 * Propagate new state to reader state
 	 */
 	rContext->readerState->readerSharing = rContext->dwContexts;
-	(void)StatSynchronize(rContext->readerState);
 
 	return SCARD_S_SUCCESS;
 }

Modified: trunk/PCSC/src/winscard_clnt.c
URL: http://svn.debian.org/wsvn/pcsclite/trunk/PCSC/src/winscard_clnt.c?rev=4434&op=diff
==============================================================================
--- trunk/PCSC/src/winscard_clnt.c (original)
+++ trunk/PCSC/src/winscard_clnt.c Tue Oct  6 09:37:51 2009
@@ -229,12 +229,9 @@
 static PCSCLITE_MUTEX clientMutex = PTHREAD_MUTEX_INITIALIZER;
 
 /**
- * Pointers to a memory mapped area used to read status information about the
- * readers.
- * Each element in the vector \ref readerStates makes references to a part of
- * the memory mapped \ref mapAddr.
- */
-static PREADER_STATE readerStates[PCSCLITE_MAX_READERS_CONTEXTS];
+ * Area used to read status information about the readers.
+ */
+static READER_STATE readerStates[PCSCLITE_MAX_READERS_CONTEXTS];
 
 PCSC_API SCARD_IO_REQUEST g_rgSCardT0Pci = { SCARD_PROTOCOL_T0, 8 };	/**< Protocol Control Information for T=0 */
 PCSC_API SCARD_IO_REQUEST g_rgSCardT1Pci = { SCARD_PROTOCOL_T1, 8 };	/**< Protocol Control Information for T=1 */
@@ -258,6 +255,7 @@
 	LPBYTE pbAttr, LPDWORD pcbAttrLen);
 
 void DESTRUCTOR SCardUnload(void);
+static LONG getReaderStates(LONG dwContextIndex);
 
 /*
  * Thread safety functions
@@ -378,7 +376,6 @@
 	LONG rv;
 	int i;
 	establish_struct scEstablishStruct;
-	sharedSegmentMsg msgStruct;
 	uint32_t dwClientID = 0;
 
 	(void)pvReserved1;
@@ -397,47 +394,10 @@
 	 */
 	if (isExecuted == 0)
 	{
-		int pageSize;
-
 		/*
 		 * Do any system initilization here
 		 */
 		(void)SYS_Initialize();
-
-		/*
-		 * Set up the memory mapped reader stats structures
-		 */
-		mapAddr = SYS_OpenFile(PCSCLITE_PUBSHM_FILE, O_RDONLY, 0);
-		if (mapAddr < 0)
-		{
-			Log3(PCSC_LOG_CRITICAL, "Cannot open public shared file %s: %s",
-				PCSCLITE_PUBSHM_FILE, strerror(errno));
-			return SCARD_E_NO_SERVICE;
-		}
-
-		/* close on exec so that child processes do not inherits the file
-		 * descriptor. The child process will call SCardEstablishContext()
-		 * if needed. */
-		(void)fcntl(mapAddr, F_SETFD, FD_CLOEXEC);
-
-		pageSize = SYS_GetPageSize();
-
-		/*
-		 * Allocate each reader structure in the memory map
-		 */
-		for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
-		{
-			readerStates[i] =
-				(PREADER_STATE)SYS_PublicMemoryMap(sizeof(READER_STATE),
-				mapAddr, (i * pageSize));
-			if (readerStates[i] == NULL)
-			{
-				Log2(PCSC_LOG_CRITICAL, "Cannot public memory map: %s",
-					strerror(errno));
-				(void)SYS_CloseFile(mapAddr);	/* Close the memory map file */
-				return SCARD_F_INTERNAL_ERROR;
-			}
-		}
 
 		/*
 		 * Initializes the application contexts and all channels for each one
@@ -484,43 +444,32 @@
 	/* Establishes a connection to the server */
 	if (SHMClientSetupSession(&dwClientID) != 0)
 	{
-		(void)SYS_CloseFile(mapAddr);
 		return SCARD_E_NO_SERVICE;
 	}
 
 	{	/* exchange client/server protocol versions */
-		version_struct *veStr;
-
-		memset(&msgStruct, 0, sizeof(msgStruct));
-		msgStruct.mtype = CMD_VERSION;
-		msgStruct.user_id = SYS_GetUID();
-		msgStruct.group_id = SYS_GetGID();
-		msgStruct.command = 0;
-		msgStruct.date = time(NULL);
-
-		veStr = &msgStruct.veStr;
-		veStr->major = PROTOCOL_VERSION_MAJOR;
-		veStr->minor = PROTOCOL_VERSION_MINOR;
-
-		if (-1 == SHMMessageSend(&msgStruct, sizeof(msgStruct), dwClientID,
-			PCSCLITE_MCLIENT_ATTEMPTS))
+		version_struct veStr;
+
+		veStr.major = PROTOCOL_VERSION_MAJOR;
+		veStr.minor = PROTOCOL_VERSION_MINOR;
+
+		if (-1 == SHMMessageSendWithHeader(CMD_VERSION, dwClientID, sizeof(veStr),
+			PCSCLITE_WRITE_TIMEOUT, &veStr))
 			return SCARD_E_NO_SERVICE;
 
-		/*
-		 * Read a message from the server
-		 */
-		if (-1 == SHMMessageReceive(&msgStruct, sizeof(msgStruct), dwClientID,
-			PCSCLITE_CLIENT_ATTEMPTS))
+		/* Read a message from the server */
+		if (-1 == SHMMessageReceive(&veStr, sizeof(veStr), dwClientID,
+			PCSCLITE_READ_TIMEOUT))
 		{
 			Log1(PCSC_LOG_CRITICAL, "Your pcscd is too old and does not support CMD_VERSION");
 			return SCARD_F_COMM_ERROR;
 		}
 
 		Log3(PCSC_LOG_INFO, "Server is protocol version %d:%d",
-			veStr->major, veStr->minor);
-
-		if (veStr->rv != SCARD_S_SUCCESS)
-			return veStr->rv;
+			veStr.major, veStr.minor);
+
+		if (veStr.rv != SCARD_S_SUCCESS)
+			return veStr.rv;
 
 		isExecuted = 1;
 	}
@@ -533,8 +482,8 @@
 	scEstablishStruct.hContext = 0;
 	scEstablishStruct.rv = SCARD_S_SUCCESS;
 
-	rv = WrapSHMWrite(SCARD_ESTABLISH_CONTEXT, dwClientID,
-		sizeof(scEstablishStruct), PCSCLITE_MCLIENT_ATTEMPTS,
+	rv = SHMMessageSendWithHeader(SCARD_ESTABLISH_CONTEXT, dwClientID,
+		sizeof(scEstablishStruct), PCSCLITE_WRITE_TIMEOUT,
 		(void *) &scEstablishStruct);
 
 	if (rv == -1)
@@ -543,12 +492,10 @@
 	/*
 	 * Read the response from the server
 	 */
-	rv = SHMClientRead(&msgStruct, dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
+	rv = SHMMessageReceive(&scEstablishStruct, sizeof(scEstablishStruct), dwClientID, PCSCLITE_READ_TIMEOUT);
 
 	if (rv == -1)
 		return SCARD_F_COMM_ERROR;
-
-	memcpy(&scEstablishStruct, &msgStruct.data, sizeof(scEstablishStruct));
 
 	if (scEstablishStruct.rv != SCARD_S_SUCCESS)
 		return scEstablishStruct.rv;
@@ -594,7 +541,6 @@
 {
 	LONG rv;
 	release_struct scReleaseStruct;
-	sharedSegmentMsg msgStruct;
 	LONG dwContextIndex;
 
 	PROFILE_START
@@ -636,10 +582,10 @@
 	scReleaseStruct.hContext = hContext;
 	scReleaseStruct.rv = SCARD_S_SUCCESS;
 
-	rv = WrapSHMWrite(SCARD_RELEASE_CONTEXT,
+	rv = SHMMessageSendWithHeader(SCARD_RELEASE_CONTEXT,
 		psContextMap[dwContextIndex].dwClientID,
 		sizeof(scReleaseStruct),
-		PCSCLITE_MCLIENT_ATTEMPTS, (void *) &scReleaseStruct);
+		PCSCLITE_WRITE_TIMEOUT, (void *) &scReleaseStruct);
 
 	if (rv == -1)
 	{
@@ -650,9 +596,9 @@
 	/*
 	 * Read a message from the server
 	 */
-	rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
-		PCSCLITE_CLIENT_ATTEMPTS);
-	memcpy(&scReleaseStruct, &msgStruct.data, sizeof(scReleaseStruct));
+	rv = SHMMessageReceive(&scReleaseStruct, sizeof(scReleaseStruct),
+		psContextMap[dwContextIndex].dwClientID,
+		PCSCLITE_READ_TIMEOUT);
 
 	if (rv == -1)
 	{
@@ -757,7 +703,6 @@
 {
 	LONG rv;
 	connect_struct scConnectStruct;
-	sharedSegmentMsg msgStruct;
 	LONG dwContextIndex;
 
 	PROFILE_START
@@ -809,9 +754,9 @@
 	scConnectStruct.dwActiveProtocol = 0;
 	scConnectStruct.rv = SCARD_S_SUCCESS;
 
-	rv = WrapSHMWrite(SCARD_CONNECT, psContextMap[dwContextIndex].dwClientID,
+	rv = SHMMessageSendWithHeader(SCARD_CONNECT, psContextMap[dwContextIndex].dwClientID,
 		sizeof(scConnectStruct),
-		PCSCLITE_CLIENT_ATTEMPTS, (void *) &scConnectStruct);
+		PCSCLITE_READ_TIMEOUT, (void *) &scConnectStruct);
 
 	if (rv == -1)
 	{
@@ -822,10 +767,9 @@
 	/*
 	 * Read a message from the server
 	 */
-	rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
-		PCSCLITE_CLIENT_ATTEMPTS);
-
-	memcpy(&scConnectStruct, &msgStruct.data, sizeof(scConnectStruct));
+	rv = SHMMessageReceive(&scConnectStruct, sizeof(scConnectStruct),
+		psContextMap[dwContextIndex].dwClientID,
+		PCSCLITE_READ_TIMEOUT);
 
 	if (rv == -1)
 	{
@@ -929,7 +873,6 @@
 {
 	LONG rv;
 	reconnect_struct scReconnectStruct;
-	sharedSegmentMsg msgStruct;
 	int i;
 	DWORD dwContextIndex, dwChannelIndex;
 
@@ -959,19 +902,24 @@
 		 * -> so the mMutex has been unlocked */
 		return SCARD_E_INVALID_HANDLE;
 
+	/* synchronize reader states with daemon */
+	rv = getReaderStates(dwContextIndex);
+	if (rv != SCARD_S_SUCCESS)
+		goto end;
+
 	for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
 	{
 		char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
 
 		/* by default r == NULL */
-		if (r && strcmp(r, (readerStates[i])->readerName) == 0)
+		if (r && strcmp(r, readerStates[i].readerName) == 0)
 			break;
 	}
 
 	if (i == PCSCLITE_MAX_READERS_CONTEXTS)
 	{
-		(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
-		return SCARD_E_READER_UNAVAILABLE;
+		rv = SCARD_E_READER_UNAVAILABLE;
+		goto end;
 	}
 
 	do
@@ -983,9 +931,9 @@
 		scReconnectStruct.dwActiveProtocol = *pdwActiveProtocol;
 		scReconnectStruct.rv = SCARD_S_SUCCESS;
 
-		rv = WrapSHMWrite(SCARD_RECONNECT, psContextMap[dwContextIndex].dwClientID,
+		rv = SHMMessageSendWithHeader(SCARD_RECONNECT, psContextMap[dwContextIndex].dwClientID,
 			sizeof(scReconnectStruct),
-			PCSCLITE_CLIENT_ATTEMPTS, (void *) &scReconnectStruct);
+			PCSCLITE_READ_TIMEOUT, (void *) &scReconnectStruct);
 
 		if (rv == -1)
 		{
@@ -996,25 +944,27 @@
 		/*
 		 * Read a message from the server
 		 */
-		rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
-			PCSCLITE_CLIENT_ATTEMPTS);
-
-		memcpy(&scReconnectStruct, &msgStruct.data, sizeof(scReconnectStruct));
+		rv = SHMMessageReceive(&scReconnectStruct,
+			sizeof(scReconnectStruct),
+			psContextMap[dwContextIndex].dwClientID,
+			PCSCLITE_READ_TIMEOUT);
 
 		if (rv == -1)
 		{
-			(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
-			return SCARD_F_COMM_ERROR;
+			rv = SCARD_F_COMM_ERROR;
+			goto end;
 		}
 	} while (SCARD_E_SHARING_VIOLATION == scReconnectStruct.rv);
 
 	*pdwActiveProtocol = scReconnectStruct.dwActiveProtocol;
-
+	rv = scReconnectStruct.rv;
+
+end:
 	(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
 
-	PROFILE_END(scReconnectStruct.rv)
-
-	return scReconnectStruct.rv;
+	PROFILE_END(rv)
+
+	return rv;
 }
 
 /**
@@ -1051,7 +1001,6 @@
 {
 	LONG rv;
 	disconnect_struct scDisconnectStruct;
-	sharedSegmentMsg msgStruct;
 	DWORD dwContextIndex, dwChannelIndex;
 
 	PROFILE_START
@@ -1081,9 +1030,9 @@
 	scDisconnectStruct.dwDisposition = dwDisposition;
 	scDisconnectStruct.rv = SCARD_S_SUCCESS;
 
-	rv = WrapSHMWrite(SCARD_DISCONNECT, psContextMap[dwContextIndex].dwClientID,
+	rv = SHMMessageSendWithHeader(SCARD_DISCONNECT, psContextMap[dwContextIndex].dwClientID,
 		sizeof(scDisconnectStruct),
-		PCSCLITE_CLIENT_ATTEMPTS, (void *) &scDisconnectStruct);
+		PCSCLITE_READ_TIMEOUT, (void *) &scDisconnectStruct);
 
 	if (rv == -1)
 	{
@@ -1094,11 +1043,10 @@
 	/*
 	 * Read a message from the server
 	 */
-	rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
-		PCSCLITE_CLIENT_ATTEMPTS);
-
-	memcpy(&scDisconnectStruct, &msgStruct.data,
-		sizeof(scDisconnectStruct));
+	rv = SHMMessageReceive(&scDisconnectStruct,
+		sizeof(scDisconnectStruct),
+		psContextMap[dwContextIndex].dwClientID,
+		PCSCLITE_READ_TIMEOUT);
 
 	if (rv == -1)
 	{
@@ -1156,7 +1104,6 @@
 	LONG rv;
 	begin_struct scBeginStruct;
 	int i;
-	sharedSegmentMsg msgStruct;
 	DWORD dwContextIndex, dwChannelIndex;
 
 	PROFILE_START
@@ -1182,19 +1129,24 @@
 		 * -> so the mMutex has been unlocked */
 		return SCARD_E_INVALID_HANDLE;
 
+	/* synchronize reader states with daemon */
+	rv = getReaderStates(dwContextIndex);
+	if (rv != SCARD_S_SUCCESS)
+		goto end;
+
 	for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
 	{
 		char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
 
 		/* by default r == NULL */
-		if (r && strcmp(r, (readerStates[i])->readerName) == 0)
+		if (r && strcmp(r, readerStates[i].readerName) == 0)
 			break;
 	}
 
 	if (i == PCSCLITE_MAX_READERS_CONTEXTS)
 	{
-		(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
-		return SCARD_E_READER_UNAVAILABLE;
+		rv = SCARD_E_READER_UNAVAILABLE;
+		goto end;
 	}
 
 	scBeginStruct.hCard = hCard;
@@ -1207,40 +1159,39 @@
 
 	do
 	{
-		rv = WrapSHMWrite(SCARD_BEGIN_TRANSACTION, psContextMap[dwContextIndex].dwClientID,
+		rv = SHMMessageSendWithHeader(SCARD_BEGIN_TRANSACTION, psContextMap[dwContextIndex].dwClientID,
 			sizeof(scBeginStruct),
-			PCSCLITE_CLIENT_ATTEMPTS, (void *) &scBeginStruct);
+			PCSCLITE_READ_TIMEOUT, (void *) &scBeginStruct);
 
 		if (rv == -1)
 		{
-
-			(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
-			return SCARD_E_NO_SERVICE;
+			rv = SCARD_E_NO_SERVICE;
+			goto end;
 		}
 
 		/*
 		 * Read a message from the server
 		 */
-		rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
-			PCSCLITE_CLIENT_ATTEMPTS);
-
-		memcpy(&scBeginStruct, &msgStruct.data, sizeof(scBeginStruct));
+		rv = SHMMessageReceive(&scBeginStruct, sizeof(scBeginStruct),
+			psContextMap[dwContextIndex].dwClientID,
+			PCSCLITE_READ_TIMEOUT);
 
 		if (rv == -1)
 		{
-
-			(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
-			return SCARD_F_COMM_ERROR;
+			rv = SCARD_F_COMM_ERROR;
+			goto end;
 		}
 
 	}
 	while (scBeginStruct.rv == SCARD_E_SHARING_VIOLATION);
-
+	rv = scBeginStruct.rv;
+
+end:
 	(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
 
-	PROFILE_END(scBeginStruct.rv);
-
-	return scBeginStruct.rv;
+	PROFILE_END(rv);
+
+	return rv;
 }
 
 /**
@@ -1287,7 +1238,6 @@
 {
 	LONG rv;
 	end_struct scEndStruct;
-	sharedSegmentMsg msgStruct;
 	int randnum, i;
 	DWORD dwContextIndex, dwChannelIndex;
 
@@ -1319,48 +1269,52 @@
 		 * -> so the mMutex has been unlocked */
 		return SCARD_E_INVALID_HANDLE;
 
+	/* synchronize reader states with daemon */
+	rv = getReaderStates(dwContextIndex);
+	if (rv != SCARD_S_SUCCESS)
+		goto end;
+
 	for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
 	{
 		char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
 
 		/* by default r == NULL */
-		if (r && strcmp(r, (readerStates[i])->readerName) == 0)
+		if (r && strcmp(r, readerStates[i].readerName) == 0)
 			break;
 	}
 
 	if (i == PCSCLITE_MAX_READERS_CONTEXTS)
 	{
-		(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
-		return SCARD_E_READER_UNAVAILABLE;
+		rv = SCARD_E_READER_UNAVAILABLE;
+		goto end;
 	}
 
 	scEndStruct.hCard = hCard;
 	scEndStruct.dwDisposition = dwDisposition;
 	scEndStruct.rv = SCARD_S_SUCCESS;
 
-	rv = WrapSHMWrite(SCARD_END_TRANSACTION,
+	rv = SHMMessageSendWithHeader(SCARD_END_TRANSACTION,
 		psContextMap[dwContextIndex].dwClientID,
 		sizeof(scEndStruct),
-		PCSCLITE_CLIENT_ATTEMPTS, (void *) &scEndStruct);
-
-	if (rv == -1)
-	{
-		(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
-		return SCARD_E_NO_SERVICE;
+		PCSCLITE_READ_TIMEOUT, (void *) &scEndStruct);
+
+	if (rv == -1)
+	{
+		rv = SCARD_E_NO_SERVICE;
+		goto end;
 	}
 
 	/*
 	 * Read a message from the server
 	 */
-	rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
-		PCSCLITE_CLIENT_ATTEMPTS);
-
-	memcpy(&scEndStruct, &msgStruct.data, sizeof(scEndStruct));
-
-	if (rv == -1)
-	{
-		(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
-		return SCARD_F_COMM_ERROR;
+	rv = SHMMessageReceive(&scEndStruct, sizeof(scEndStruct),
+		psContextMap[dwContextIndex].dwClientID,
+		PCSCLITE_READ_TIMEOUT);
+
+	if (rv == -1)
+	{
+		rv = SCARD_F_COMM_ERROR;
+		goto end;
 	}
 
 	/*
@@ -1368,12 +1322,14 @@
 	 */
 	randnum = SYS_RandomInt(1000, 10000);
 	(void)SYS_USleep(randnum);
-
+	rv = scEndStruct.rv;
+
+end:
 	(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
 
-	PROFILE_END(scEndStruct.rv)
-
-	return scEndStruct.rv;
+	PROFILE_END(rv)
+
+	return rv;
 }
 
 /**
@@ -1385,8 +1341,7 @@
 LONG SCardCancelTransaction(SCARDHANDLE hCard)
 {
 	LONG rv;
-	cancel_struct scCancelStruct;
-	sharedSegmentMsg msgStruct;
+	cancel_transaction_struct scCancelStruct;
 	int i;
 	DWORD dwContextIndex, dwChannelIndex;
 
@@ -1413,53 +1368,59 @@
 		 * -> so the mMutex has been unlocked */
 		return SCARD_E_INVALID_HANDLE;
 
+	/* synchronize reader states with daemon */
+	rv = getReaderStates(dwContextIndex);
+	if (rv != SCARD_S_SUCCESS)
+		goto end;
+
 	for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
 	{
 		char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
 
 		/* by default r == NULL */
-		if (r && strcmp(r, (readerStates[i])->readerName) == 0)
+		if (r && strcmp(r, readerStates[i].readerName) == 0)
 			break;
 	}
 
 	if (i == PCSCLITE_MAX_READERS_CONTEXTS)
 	{
-		(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
-		return SCARD_E_READER_UNAVAILABLE;
+		rv = SCARD_E_READER_UNAVAILABLE;
+		goto end;
 	}
 
 	scCancelStruct.hCard = hCard;
 
-	rv = WrapSHMWrite(SCARD_CANCEL_TRANSACTION,
+	rv = SHMMessageSendWithHeader(SCARD_CANCEL_TRANSACTION,
 		psContextMap[dwContextIndex].dwClientID,
 		sizeof(scCancelStruct),
-		PCSCLITE_CLIENT_ATTEMPTS, (void *) &scCancelStruct);
-
-	if (rv == -1)
-	{
-		(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
-		return SCARD_E_NO_SERVICE;
+		PCSCLITE_READ_TIMEOUT, (void *) &scCancelStruct);
+
+	if (rv == -1)
+	{
+		rv = SCARD_E_NO_SERVICE;
+		goto end;
 	}
 
 	/*
 	 * Read a message from the server
 	 */
-	rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
-		PCSCLITE_CLIENT_ATTEMPTS);
-
-	memcpy(&scCancelStruct, &msgStruct.data, sizeof(scCancelStruct));
-
-	if (rv == -1)
-	{
-		(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
-		return SCARD_F_COMM_ERROR;
-	}
-
+	rv = SHMMessageReceive(&scCancelStruct, sizeof(scCancelStruct),
+		psContextMap[dwContextIndex].dwClientID,
+		PCSCLITE_READ_TIMEOUT);
+
+	if (rv == -1)
+	{
+		rv = SCARD_F_COMM_ERROR;
+		goto end;
+	}
+	rv = scCancelStruct.rv;
+
+end:
 	(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
 
-	PROFILE_END(scCancelStruct.rv)
-
-	return scCancelStruct.rv;
+	PROFILE_END(rv)
+
+	return rv;
 }
 
 /**
@@ -1557,7 +1518,6 @@
 	LONG rv;
 	int i;
 	status_struct scStatusStruct;
-	sharedSegmentMsg msgStruct;
 	DWORD dwContextIndex, dwChannelIndex;
 	char *r;
 	char *bufReader = NULL;
@@ -1608,11 +1568,16 @@
 		 * -> so the mMutex has been unlocked */
 		return SCARD_E_INVALID_HANDLE;
 
+	/* synchronize reader states with daemon */
+	rv = getReaderStates(dwContextIndex);
+	if (rv != SCARD_S_SUCCESS)
+		goto end;
+
 	r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
 	for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
 	{
 		/* by default r == NULL */
-		if (r && strcmp(r, (readerStates[i])->readerName) == 0)
+		if (r && strcmp(r, readerStates[i].readerName) == 0)
 			break;
 	}
 
@@ -1630,9 +1595,9 @@
 	scStatusStruct.pcchReaderLen = sizeof(scStatusStruct.mszReaderNames);
 	scStatusStruct.pcbAtrLen = sizeof(scStatusStruct.pbAtr);
 
-	rv = WrapSHMWrite(SCARD_STATUS, psContextMap[dwContextIndex].dwClientID,
+	rv = SHMMessageSendWithHeader(SCARD_STATUS, psContextMap[dwContextIndex].dwClientID,
 		sizeof(scStatusStruct),
-		PCSCLITE_CLIENT_ATTEMPTS, (void *) &scStatusStruct);
+		PCSCLITE_READ_TIMEOUT, (void *) &scStatusStruct);
 
 	if (rv == -1)
 	{
@@ -1643,10 +1608,9 @@
 	/*
 	 * Read a message from the server
 	 */
-	rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
-		PCSCLITE_CLIENT_ATTEMPTS);
-
-	memcpy(&scStatusStruct, &msgStruct.data, sizeof(scStatusStruct));
+	rv = SHMMessageReceive(&scStatusStruct, sizeof(scStatusStruct),
+		psContextMap[dwContextIndex].dwClientID,
+		PCSCLITE_READ_TIMEOUT);
 
 	if (rv == -1)
 	{
@@ -1668,13 +1632,13 @@
 	 */
 
 	*pcchReaderLen = strlen(psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName) + 1;
-	*pcbAtrLen = (readerStates[i])->cardAtrLength;
+	*pcbAtrLen = readerStates[i].cardAtrLength;
 
 	if (pdwState)
-		*pdwState = (readerStates[i])->readerState;
+		*pdwState = readerStates[i].readerState;
 
 	if (pdwProtocol)
-		*pdwProtocol = (readerStates[i])->cardProtocol;
+		*pdwProtocol = readerStates[i].cardProtocol;
 
 	if (SCARD_AUTOALLOCATE == dwReaderLen)
 	{
@@ -1730,7 +1694,7 @@
 		if (*pcbAtrLen > dwAtrLen)
 			rv = SCARD_E_INSUFFICIENT_BUFFER;
 
-		memcpy(bufAtr, (readerStates[i])->cardAtr, min(*pcbAtrLen, dwAtrLen));
+		memcpy(bufAtr, readerStates[i].cardAtr, min(*pcbAtrLen, dwAtrLen));
 	}
 
 end:
@@ -1739,63 +1703,6 @@
 	PROFILE_END(rv)
 
 	return rv;
-}
-
-static long WaitForPcscdEvent(SCARDCONTEXT hContext, long dwTime)
-{
-	char filename[FILENAME_MAX];
-	char buf[1];
-	int fd, r;
-	struct timeval tv, *ptv = NULL;
-	struct timeval before, after;
-	fd_set read_fd;
-
-	if (INFINITE != dwTime)
-	{
-		if (dwTime < 0)
-			return 0;
-		gettimeofday(&before, NULL);
-		tv.tv_sec = dwTime/1000;
-		tv.tv_usec = dwTime*1000 - tv.tv_sec*1000000;
-		ptv = &tv;
-	}
-
-	(void)snprintf(filename, sizeof(filename), "%s/event.%d.%ld",
-		PCSCLITE_EVENTS_DIR, SYS_GetPID(), hContext);
-	r = mkfifo(filename, 0644);
-	if (-1 == r)
-	{
-		Log2(PCSC_LOG_CRITICAL, "Can't create event fifo: %s", strerror(errno));
-		goto exit;
-	}
-
-	fd = SYS_OpenFile(filename, O_RDONLY | O_NONBLOCK, 0);
-
-	/* the file may have been removed between the mkfifo() and open() */
-	if (-1 != fd)
-	{
-		FD_ZERO(&read_fd);
-		FD_SET(fd, &read_fd);
-		
-		(void)select(fd+1, &read_fd, NULL, NULL, ptv);
-
-		(void)SYS_ReadFile(fd, buf, 1);
-		(void)SYS_CloseFile(fd);
-	}
-
-	(void)SYS_RemoveFile(filename);
-
-	if (INFINITE != dwTime)
-	{
-		long int diff;
-
-		gettimeofday(&after, NULL);
-		diff = time_sub(&after, &before);
-		dwTime -= diff/1000;
-	}
-
-exit:
-	return dwTime;
 }
 
 /**
@@ -1894,7 +1801,7 @@
 {
 	PSCARD_READERSTATE_A currReader;
 	PREADER_STATE rContext;
-	long dwTime = dwTimeout;
+	long dwTime;
 	DWORD dwState;
 	DWORD dwBreakFlag = 0;
 	int j;
@@ -1952,6 +1859,11 @@
 		 * -> so the mMutex has been unlocked */
 		return SCARD_E_INVALID_HANDLE;
 
+	/* synchronize reader states with daemon */
+	rv = getReaderStates(dwContextIndex);
+	if (rv != SCARD_S_SUCCESS)
+		goto end;
+
 	/* Clear the event state for all readers */
 	for (j = 0; j < cReaders; j++)
 		rgReaderStates[j].dwEventState = 0;
@@ -1963,8 +1875,13 @@
 
 	/* Get the initial reader count on the system */
 	for (j=0; j < PCSCLITE_MAX_READERS_CONTEXTS; j++)
-		if ((readerStates[j])->readerID != 0)
+		if (readerStates[j].readerID != 0)
 			currentReaderCount++;
+
+	if (INFINITE == dwTimeout)
+		dwTime = 60*1000;	/* "infinite" timeout */
+	else
+		dwTime = dwTimeout;
 
 	j = 0;
 	do
@@ -1994,7 +1911,7 @@
 
 			for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
 			{
-				if (strcmp(lpcReaderName, (readerStates[i])->readerName) == 0)
+				if (strcmp(lpcReaderName, readerStates[i].readerName) == 0)
 					break;
 			}
 
@@ -2007,7 +1924,7 @@
 					int k, newReaderCount = 0;
 
 					for (k=0; k < PCSCLITE_MAX_READERS_CONTEXTS; k++)
-						if ((readerStates[k])->readerID != 0)
+						if (readerStates[k].readerID != 0)
 							newReaderCount++;
 
 					if (newReaderCount != currentReaderCount)
@@ -2048,7 +1965,7 @@
 	/*****************************************************************/
 
 				/* Set the reader status structure */
-				rContext = readerStates[i];
+				rContext = &readerStates[i];
 
 				/* Now we check all the Reader States */
 				dwState = rContext->readerState;
@@ -2255,7 +2172,80 @@
 				break;
 
 			/* Only sleep once for each cycle of reader checks. */
-			dwTime = WaitForPcscdEvent(hContext, dwTime);
+			{
+				struct wait_reader_state_change waitStatusStruct;
+				struct timeval before, after;
+
+				gettimeofday(&before, NULL);
+
+				waitStatusStruct.timeOut = dwTime;
+
+				rv = SHMMessageSendWithHeader(CMD_WAIT_READER_STATE_CHANGE,
+					psContextMap[dwContextIndex].dwClientID,
+					sizeof(waitStatusStruct), PCSCLITE_WRITE_TIMEOUT,
+					&waitStatusStruct);
+
+				if (rv == -1)
+				{
+					rv = SCARD_E_NO_SERVICE;
+					goto end;
+				}
+
+				/*
+				 * Read a message from the server
+				 */
+				rv = SHMMessageReceive(&waitStatusStruct, sizeof(waitStatusStruct),
+					psContextMap[dwContextIndex].dwClientID,
+					dwTime);
+
+				/* timeout */
+				if (-1 == rv)
+				{
+					/* aask server to remove us from the event list */
+					rv = SHMMessageSendWithHeader(CMD_STOP_WAITING_READER_STATE_CHANGE,
+						psContextMap[dwContextIndex].dwClientID,
+						sizeof(waitStatusStruct), PCSCLITE_WRITE_TIMEOUT,
+						&waitStatusStruct);
+
+					if (rv == -1)
+					{
+						rv = SCARD_E_NO_SERVICE;
+						goto end;
+					}
+
+					/* Read a message from the server */
+					rv = SHMMessageReceive(&waitStatusStruct, sizeof(waitStatusStruct),
+						psContextMap[dwContextIndex].dwClientID,
+						dwTime);
+
+					if (rv == -1)
+					{
+						rv = SCARD_E_NO_SERVICE;
+						goto end;
+					}
+				}
+
+				/* an event occurs or SCardCancel() was called */
+				if (SCARD_S_SUCCESS != waitStatusStruct.rv)
+				{
+					rv = waitStatusStruct.rv;
+					goto end;
+				}
+
+				/* synchronize reader states with daemon */
+				rv = getReaderStates(dwContextIndex);
+				if (rv != SCARD_S_SUCCESS)
+					goto end;
+
+				if (INFINITE != dwTimeout)
+				{
+					long int diff;
+
+					gettimeofday(&after, NULL);
+					diff = time_sub(&after, &before);
+					dwTime -= diff/1000;
+				}
+			}
 
 			if (dwTimeout != INFINITE)
 			{
@@ -2341,8 +2331,7 @@
 	LPDWORD lpBytesReturned)
 {
 	LONG rv;
-	control_struct scControlStruct;
-	sharedSegmentMsg msgStruct;
+	struct control_struct scControlStruct;
 	int i;
 	DWORD dwContextIndex, dwChannelIndex;
 
@@ -2376,155 +2365,92 @@
 		 * -> so the mMutex has been unlocked */
 		return SCARD_E_INVALID_HANDLE;
 
+	/* synchronize reader states with daemon */
+	rv = getReaderStates(dwContextIndex);
+	if (rv != SCARD_S_SUCCESS)
+		goto end;
+
 	for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
 	{
 		char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
 
 		/* by default r == NULL */
-		if (r && strcmp(r, (readerStates[i])->readerName) == 0)
+		if (r && strcmp(r, readerStates[i].readerName) == 0)
 			break;
 	}
 
 	if (i == PCSCLITE_MAX_READERS_CONTEXTS)
 	{
-		(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
-		return SCARD_E_READER_UNAVAILABLE;
+		rv = SCARD_E_READER_UNAVAILABLE;
+		goto end;
 	}
 
 	if ((cbSendLength > MAX_BUFFER_SIZE_EXTENDED)
 		|| (cbRecvLength > MAX_BUFFER_SIZE_EXTENDED))
 	{
-		(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
-		return SCARD_E_INSUFFICIENT_BUFFER;
-	}
-
-	if ((cbSendLength > MAX_BUFFER_SIZE) || (cbRecvLength > MAX_BUFFER_SIZE))
-	{
-		/* extended control */
-		unsigned char buffer[sizeof(sharedSegmentMsg) + MAX_BUFFER_SIZE_EXTENDED];
-		control_struct_extended *scControlStructExtended = (control_struct_extended *)buffer;
-		sharedSegmentMsg *pmsgStruct = (psharedSegmentMsg)buffer;
-
-		scControlStructExtended->hCard = hCard;
-		scControlStructExtended->dwControlCode = dwControlCode;
-		scControlStructExtended->cbSendLength = cbSendLength;
-		scControlStructExtended->cbRecvLength = cbRecvLength;
-		scControlStructExtended->dwBytesReturned = 0;
-		scControlStructExtended->rv = SCARD_S_SUCCESS;
-		/* The size of data to send is the size of
-		 * struct control_struct_extended WITHOUT the data[] field
-		 * plus the effective data[] size
-		 */
-		scControlStructExtended->size = sizeof(*scControlStructExtended)
-			- (sizeof(control_struct_extended) - offsetof(control_struct_extended, data))
-			+ cbSendLength;
-		memcpy(scControlStructExtended->data, pbSendBuffer, cbSendLength);
-
-		rv = WrapSHMWrite(SCARD_CONTROL_EXTENDED,
+		rv = SCARD_E_INSUFFICIENT_BUFFER;
+		goto end;
+	}
+
+	scControlStruct.hCard = hCard;
+	scControlStruct.dwControlCode = dwControlCode;
+	scControlStruct.cbSendLength = cbSendLength;
+	scControlStruct.cbRecvLength = cbRecvLength;
+
+	rv = SHMMessageSendWithHeader(SCARD_CONTROL,
+		psContextMap[dwContextIndex].dwClientID,
+		sizeof(scControlStruct), PCSCLITE_READ_TIMEOUT, &scControlStruct);
+
+	if (rv == -1)
+	{
+		rv = SCARD_E_NO_SERVICE;
+		goto end;
+	}
+
+	/* write the sent buffer */
+	rv = SHMMessageSend((char *)pbSendBuffer, cbSendLength,
+		psContextMap[dwContextIndex].dwClientID, PCSCLITE_WRITE_TIMEOUT);
+
+	if (rv == -1)
+	{
+		rv = SCARD_E_NO_SERVICE;
+		goto end;
+	}
+
+	/*
+	 * Read a message from the server
+	 */
+	rv = SHMMessageReceive(&scControlStruct, sizeof(scControlStruct),
+		psContextMap[dwContextIndex].dwClientID,
+		PCSCLITE_READ_TIMEOUT);
+
+	if (rv == -1)
+	{
+		rv = SCARD_F_COMM_ERROR;
+		goto end;
+	}
+
+	if (SCARD_S_SUCCESS == scControlStruct.rv)
+	{
+		/* read the received buffer */
+		rv = SHMMessageReceive(pbRecvBuffer, scControlStruct.dwBytesReturned,
 			psContextMap[dwContextIndex].dwClientID,
-			scControlStructExtended->size,
-			PCSCLITE_CLIENT_ATTEMPTS, buffer);
+			PCSCLITE_READ_TIMEOUT);
 
 		if (rv == -1)
 		{
-			(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
-			return SCARD_E_NO_SERVICE;
+			rv = SCARD_E_NO_SERVICE;
+			goto end;
 		}
 
-		/*
-		 * Read a message from the server
-		 */
-		/* read the first block */
-		rv = SHMMessageReceive(buffer, sizeof(sharedSegmentMsg),
-			psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
-		if (rv == -1)
-		{
-			(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
-			return SCARD_F_COMM_ERROR;
-		}
-
-		/* we receive a sharedSegmentMsg and not a control_struct_extended */
-		scControlStructExtended = (control_struct_extended *)&(pmsgStruct -> data);
-
-		/* a second block is present */
-		if (scControlStructExtended->size > PCSCLITE_MAX_MESSAGE_SIZE)
-		{
-			rv = SHMMessageReceive(buffer + sizeof(sharedSegmentMsg),
-				scControlStructExtended->size-PCSCLITE_MAX_MESSAGE_SIZE,
-				psContextMap[dwContextIndex].dwClientID,
-				PCSCLITE_CLIENT_ATTEMPTS);
-			if (rv == -1)
-			{
-				(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
-				return SCARD_F_COMM_ERROR;
-			}
-		}
-
-		if (scControlStructExtended -> rv == SCARD_S_SUCCESS)
-		{
-			/*
-			 * Copy and zero it so any secret information is not leaked
-			 */
-			memcpy(pbRecvBuffer, scControlStructExtended -> data,
-				scControlStructExtended -> dwBytesReturned);
-			memset(scControlStructExtended -> data, 0x00,
-				scControlStructExtended -> dwBytesReturned);
-		}
-
-		if (NULL != lpBytesReturned)
-			*lpBytesReturned = scControlStructExtended -> dwBytesReturned;
-
-		rv = scControlStructExtended -> rv;
-	}
-	else
-	{
-		scControlStruct.hCard = hCard;
-		scControlStruct.dwControlCode = dwControlCode;
-		scControlStruct.cbSendLength = cbSendLength;
-		scControlStruct.cbRecvLength = cbRecvLength;
-		memcpy(scControlStruct.pbSendBuffer, pbSendBuffer, cbSendLength);
-
-		rv = WrapSHMWrite(SCARD_CONTROL,
-			psContextMap[dwContextIndex].dwClientID,
-			sizeof(scControlStruct), PCSCLITE_CLIENT_ATTEMPTS, &scControlStruct);
-
-		if (rv == -1)
-		{
-			(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
-			return SCARD_E_NO_SERVICE;
-		}
-
-		/*
-		 * Read a message from the server
-		 */
-		rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
-			PCSCLITE_CLIENT_ATTEMPTS);
-
-		if (rv == -1)
-		{
-			(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
-			return SCARD_F_COMM_ERROR;
-		}
-
-		memcpy(&scControlStruct, &msgStruct.data, sizeof(scControlStruct));
-
-		if (NULL != lpBytesReturned)
-			*lpBytesReturned = scControlStruct.dwBytesReturned;
-
-		if (scControlStruct.rv == SCARD_S_SUCCESS)
-		{
-			/*
-			 * Copy and zero it so any secret information is not leaked
-			 */
-			memcpy(pbRecvBuffer, scControlStruct.pbRecvBuffer,
-				scControlStruct.cbRecvLength);
-			memset(scControlStruct.pbRecvBuffer, 0x00,
-				sizeof(scControlStruct.pbRecvBuffer));
-		}
-
-		rv = scControlStruct.rv;
-	}
-
+	}
+
+	if (NULL != lpBytesReturned)
+		*lpBytesReturned = scControlStruct.dwBytesReturned;
+
+	rv = scControlStruct.rv;
+
+end:
 	(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
 
 	PROFILE_END(rv)
@@ -2728,8 +2654,7 @@
 	LPBYTE pbAttr, LPDWORD pcbAttrLen)
 {
 	LONG rv;
-	getset_struct scGetSetStruct;
-	sharedSegmentMsg msgStruct;
+	struct getset_struct scGetSetStruct;
 	int i;
 	DWORD dwContextIndex, dwChannelIndex;
 
@@ -2754,25 +2679,30 @@
 		 * -> so the mMutex has been unlocked */
 		return SCARD_E_INVALID_HANDLE;
 
+	/* synchronize reader states with daemon */
+	rv = getReaderStates(dwContextIndex);
+	if (rv != SCARD_S_SUCCESS)
+		goto end;
+
 	for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
 	{
 		char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
 
 		/* by default r == NULL */
-		if (r && strcmp(r, (readerStates[i])->readerName) == 0)
+		if (r && strcmp(r, readerStates[i].readerName) == 0)
 			break;
 	}
 
 	if (i == PCSCLITE_MAX_READERS_CONTEXTS)
 	{
-		(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
-		return SCARD_E_READER_UNAVAILABLE;
+		rv = SCARD_E_READER_UNAVAILABLE;
+		goto end;
 	}
 
 	if (*pcbAttrLen > MAX_BUFFER_SIZE)
 	{
-		(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
-		return SCARD_E_INSUFFICIENT_BUFFER;
+		rv = SCARD_E_INSUFFICIENT_BUFFER;
+		goto end;
 	}
 
 	scGetSetStruct.hCard = hCard;
@@ -2783,29 +2713,28 @@
 	if (SCARD_SET_ATTRIB == command)
 		memcpy(scGetSetStruct.pbAttr, pbAttr, *pcbAttrLen);
 
-	rv = WrapSHMWrite(command,
+	rv = SHMMessageSendWithHeader(command,
 		psContextMap[dwContextIndex].dwClientID, sizeof(scGetSetStruct),
-		PCSCLITE_CLIENT_ATTEMPTS, &scGetSetStruct);
-
-	if (rv == -1)
-	{
-		(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
-		return SCARD_E_NO_SERVICE;
+		PCSCLITE_READ_TIMEOUT, &scGetSetStruct);
+
+	if (rv == -1)
+	{
+		rv = SCARD_E_NO_SERVICE;
+		goto end;
 	}
 
 	/*
 	 * Read a message from the server
 	 */
-	rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
-		PCSCLITE_CLIENT_ATTEMPTS);
-
-	if (rv == -1)
-	{
-		(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
-		return SCARD_F_COMM_ERROR;
-	}
-
-	memcpy(&scGetSetStruct, &msgStruct.data, sizeof(scGetSetStruct));
+	rv = SHMMessageReceive(&scGetSetStruct, sizeof(scGetSetStruct),
+		psContextMap[dwContextIndex].dwClientID,
+		PCSCLITE_READ_TIMEOUT);
+
+	if (rv == -1)
+	{
+		rv = SCARD_F_COMM_ERROR;
+		goto end;
+	}
 
 	if ((SCARD_S_SUCCESS == scGetSetStruct.rv) && (SCARD_GET_ATTRIB == command))
 	{
@@ -2825,10 +2754,12 @@
 
 		memset(scGetSetStruct.pbAttr, 0x00, sizeof(scGetSetStruct.pbAttr));
 	}
-
+	rv = scGetSetStruct.rv;
+
+end:
 	(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
 
-	return scGetSetStruct.rv;
+	return rv;
 }
 
 /**
@@ -2897,6 +2828,7 @@
 	LONG rv;
 	int i;
 	DWORD dwContextIndex, dwChannelIndex;
+	struct transmit_struct scTransmitStruct;
 
 	PROFILE_START
 
@@ -2929,200 +2861,109 @@
 		 * -> so the mMutex has been unlocked */
 		return SCARD_E_INVALID_HANDLE;
 
+	/* synchronize reader states with daemon */
+	rv = getReaderStates(dwContextIndex);
+	if (rv != SCARD_S_SUCCESS)
+		goto end;
+
 	for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
 	{
 		char *r = psContextMap[dwContextIndex].psChannelMap[dwChannelIndex].readerName;
 
 		/* by default r == NULL */
-		if (r && strcmp(r, (readerStates[i])->readerName) == 0)
+		if (r && strcmp(r, readerStates[i].readerName) == 0)
 			break;
 	}
 
 	if (i == PCSCLITE_MAX_READERS_CONTEXTS)
 	{
-		(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
-		return SCARD_E_READER_UNAVAILABLE;
+		rv = SCARD_E_READER_UNAVAILABLE;
+		goto end;
 	}
 
 	if ((cbSendLength > MAX_BUFFER_SIZE_EXTENDED)
 		|| (*pcbRecvLength > MAX_BUFFER_SIZE_EXTENDED))
 	{
-		(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
-		return SCARD_E_INSUFFICIENT_BUFFER;
-	}
-
-	if ((cbSendLength > MAX_BUFFER_SIZE) || (*pcbRecvLength > MAX_BUFFER_SIZE))
-	{
-		/* extended APDU */
-		unsigned char buffer[sizeof(sharedSegmentMsg) + MAX_BUFFER_SIZE_EXTENDED];
-		transmit_struct_extended *scTransmitStructExtended = (transmit_struct_extended *)buffer;
-		sharedSegmentMsg *pmsgStruct = (psharedSegmentMsg)buffer;
-
-		scTransmitStructExtended->hCard = hCard;
-		scTransmitStructExtended->cbSendLength = cbSendLength;
-		scTransmitStructExtended->pcbRecvLength = *pcbRecvLength;
-		/* The size of data to send is the size of
-		 * struct control_struct_extended WITHOUT the data[] field
-		 * plus the effective data[] size
-		 */
-		scTransmitStructExtended->size = sizeof(*scTransmitStructExtended)
-			- (sizeof(transmit_struct_extended) - offsetof(transmit_struct_extended, data))
-			+ cbSendLength;
-		scTransmitStructExtended->ioSendPciProtocol = pioSendPci->dwProtocol;
-		scTransmitStructExtended->ioSendPciLength = pioSendPci->cbPciLength;
-		memcpy(scTransmitStructExtended->data, pbSendBuffer, cbSendLength);
-		scTransmitStructExtended->rv = SCARD_S_SUCCESS;
+		rv = SCARD_E_INSUFFICIENT_BUFFER;
+		goto end;
+	}
+
+	scTransmitStruct.hCard = hCard;
+	scTransmitStruct.cbSendLength = cbSendLength;
+	scTransmitStruct.pcbRecvLength = *pcbRecvLength;
+	scTransmitStruct.ioSendPciProtocol = pioSendPci->dwProtocol;
+	scTransmitStruct.ioSendPciLength = pioSendPci->cbPciLength;
+	scTransmitStruct.rv = SCARD_S_SUCCESS;
+
+	if (pioRecvPci)
+	{
+		scTransmitStruct.ioRecvPciProtocol = pioRecvPci->dwProtocol;
+		scTransmitStruct.ioRecvPciLength = pioRecvPci->cbPciLength;
+	}
+	else
+	{
+		scTransmitStruct.ioRecvPciProtocol = SCARD_PROTOCOL_ANY;
+		scTransmitStruct.ioRecvPciLength = sizeof(SCARD_IO_REQUEST);
+	}
+
+	rv = SHMMessageSendWithHeader(SCARD_TRANSMIT,
+		psContextMap[dwContextIndex].dwClientID, sizeof(scTransmitStruct),
+		PCSCLITE_WRITE_TIMEOUT, (void *) &scTransmitStruct);
+
+	if (rv == -1)
+	{
+		rv = SCARD_E_NO_SERVICE;
+		goto end;
+	}
+
+	/* write the sent buffer */
+	rv = SHMMessageSend((void *)pbSendBuffer, cbSendLength,
+		psContextMap[dwContextIndex].dwClientID, PCSCLITE_WRITE_TIMEOUT);
+
+	if (rv == -1)
+	{
+		rv = SCARD_E_NO_SERVICE;
+		goto end;
+	}
+
+	/*
+	 * Read a message from the server
+	 */
+	rv = SHMMessageReceive(&scTransmitStruct, sizeof(scTransmitStruct),
+		psContextMap[dwContextIndex].dwClientID,
+		PCSCLITE_READ_TIMEOUT);
+
+	if (rv == -1)
+	{
+		rv = SCARD_F_COMM_ERROR;
+		goto end;
+	}
+
+	if (SCARD_S_SUCCESS == scTransmitStruct.rv)
+	{
+		/* read the received buffer */
+		rv = SHMMessageReceive(pbRecvBuffer, scTransmitStruct.pcbRecvLength,
+			psContextMap[dwContextIndex].dwClientID,
+			PCSCLITE_READ_TIMEOUT);
+
+		if (rv == -1)
+		{
+			rv = SCARD_E_NO_SERVICE;
+			goto end;
+		}
 
 		if (pioRecvPci)
 		{
-			scTransmitStructExtended->ioRecvPciProtocol = pioRecvPci->dwProtocol;
-			scTransmitStructExtended->ioRecvPciLength = pioRecvPci->cbPciLength;
+			pioRecvPci->dwProtocol = scTransmitStruct.ioRecvPciProtocol;
+			pioRecvPci->cbPciLength = scTransmitStruct.ioRecvPciLength;
 		}
-		else
-		{
-			scTransmitStructExtended->ioRecvPciProtocol = SCARD_PROTOCOL_ANY;
-			scTransmitStructExtended->ioRecvPciLength = sizeof(SCARD_IO_REQUEST);
-		}
-
-		rv = WrapSHMWrite(SCARD_TRANSMIT_EXTENDED,
-			psContextMap[dwContextIndex].dwClientID,
-			scTransmitStructExtended->size,
-			PCSCLITE_CLIENT_ATTEMPTS, buffer);
-
-		if (rv == -1)
-		{
-			(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
-			return SCARD_E_NO_SERVICE;
-		}
-
-		/*
-		 * Read a message from the server
-		 */
-		/* read the first block */
-		rv = SHMMessageReceive(buffer, sizeof(sharedSegmentMsg), psContextMap[dwContextIndex].dwClientID, PCSCLITE_CLIENT_ATTEMPTS);
-		if (rv == -1)
-		{
-			(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
-			return SCARD_F_COMM_ERROR;
-		}
-
-		/* we receive a sharedSegmentMsg and not a transmit_struct_extended */
-		scTransmitStructExtended = (transmit_struct_extended *)&(pmsgStruct -> data);
-
-		/* a second block is present */
-		if (scTransmitStructExtended->size > PCSCLITE_MAX_MESSAGE_SIZE)
-		{
-			rv = SHMMessageReceive(buffer + sizeof(sharedSegmentMsg),
-				scTransmitStructExtended->size-PCSCLITE_MAX_MESSAGE_SIZE,
-				psContextMap[dwContextIndex].dwClientID,
-				PCSCLITE_CLIENT_ATTEMPTS);
-			if (rv == -1)
-			{
-				(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
-				return SCARD_F_COMM_ERROR;
-			}
-		}
-
-		if (scTransmitStructExtended -> rv == SCARD_S_SUCCESS)
-		{
-			/*
-			 * Copy and zero it so any secret information is not leaked
-			 */
-			memcpy(pbRecvBuffer, scTransmitStructExtended -> data,
-				scTransmitStructExtended -> pcbRecvLength);
-			memset(scTransmitStructExtended -> data, 0x00,
-				scTransmitStructExtended -> pcbRecvLength);
-
-			if (pioRecvPci)
-			{
-				pioRecvPci->dwProtocol = scTransmitStructExtended->ioRecvPciProtocol;
-				pioRecvPci->cbPciLength = scTransmitStructExtended->ioRecvPciLength;
-			}
-		}
-
-		*pcbRecvLength = scTransmitStructExtended -> pcbRecvLength;
-		(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
-
-		rv = scTransmitStructExtended -> rv;
-	}
-	else
-	{
-		/* short APDU */
-		transmit_struct scTransmitStruct;
-		sharedSegmentMsg msgStruct;
-
-		scTransmitStruct.hCard = hCard;
-		scTransmitStruct.cbSendLength = cbSendLength;
-		scTransmitStruct.pcbRecvLength = *pcbRecvLength;
-		scTransmitStruct.ioSendPciProtocol = pioSendPci->dwProtocol;
-		scTransmitStruct.ioSendPciLength = pioSendPci->cbPciLength;
-		memcpy(scTransmitStruct.pbSendBuffer, pbSendBuffer, cbSendLength);
-		memset(scTransmitStruct.pbSendBuffer+cbSendLength, 0, sizeof(scTransmitStruct.pbSendBuffer)-cbSendLength);
-		memset(scTransmitStruct.pbRecvBuffer, 0, sizeof(scTransmitStruct.pbRecvBuffer));
-		scTransmitStruct.rv = SCARD_S_SUCCESS;
-
-		if (pioRecvPci)
-		{
-			scTransmitStruct.ioRecvPciProtocol = pioRecvPci->dwProtocol;
-			scTransmitStruct.ioRecvPciLength = pioRecvPci->cbPciLength;
-		}
-		else
-		{
-			scTransmitStruct.ioRecvPciProtocol = SCARD_PROTOCOL_ANY;
-			scTransmitStruct.ioRecvPciLength = sizeof(SCARD_IO_REQUEST);
-		}
-
-		rv = WrapSHMWrite(SCARD_TRANSMIT,
-			psContextMap[dwContextIndex].dwClientID, sizeof(scTransmitStruct),
-			PCSCLITE_CLIENT_ATTEMPTS, (void *) &scTransmitStruct);
-
-		if (rv == -1)
-		{
-			(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
-			return SCARD_E_NO_SERVICE;
-		}
-
-		/*
-		 * Read a message from the server
-		 */
-		rv = SHMClientRead(&msgStruct, psContextMap[dwContextIndex].dwClientID,
-			PCSCLITE_CLIENT_ATTEMPTS);
-
-		memcpy(&scTransmitStruct, &msgStruct.data, sizeof(scTransmitStruct));
-
-		if (rv == -1)
-		{
-			(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
-			return SCARD_F_COMM_ERROR;
-		}
-
-		/*
-		 * Zero it and free it so any secret information cannot be leaked
-		 */
-		memset(scTransmitStruct.pbSendBuffer, 0x00, cbSendLength);
-
-		if (scTransmitStruct.rv == SCARD_S_SUCCESS)
-		{
-			/*
-			 * Copy and zero it so any secret information is not leaked
-			 */
-			memcpy(pbRecvBuffer, scTransmitStruct.pbRecvBuffer,
-				scTransmitStruct.pcbRecvLength);
-			memset(scTransmitStruct.pbRecvBuffer, 0x00,
-				scTransmitStruct.pcbRecvLength);
-
-			if (pioRecvPci)
-			{
-				pioRecvPci->dwProtocol = scTransmitStruct.ioRecvPciProtocol;
-				pioRecvPci->cbPciLength = scTransmitStruct.ioRecvPciLength;
-			}
-		}
-
-		*pcbRecvLength = scTransmitStruct.pcbRecvLength;
-		(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
-
-		rv = scTransmitStruct.rv;
-	}
+	}
+
+	*pcbRecvLength = scTransmitStruct.pcbRecvLength;
+	rv = scTransmitStruct.rv;
+
+end:
+	(void)SYS_MutexUnLock(psContextMap[dwContextIndex].mMutex);
 
 	PROFILE_END(rv)
 
@@ -3180,7 +3021,7 @@
 LONG SCardListReaders(SCARDCONTEXT hContext, /*@unused@*/ LPCSTR mszGroups,
 	LPSTR mszReaders, LPDWORD pcchReaders)
 {
-	DWORD dwReadersLen;
+	DWORD dwReadersLen = 0;
 	int i;
 	LONG dwContextIndex;
 	LONG rv = SCARD_S_SUCCESS;
@@ -3219,10 +3060,15 @@
 		 * -> so the mMutex has been unlocked */
 		return SCARD_E_INVALID_HANDLE;
 
+	/* synchronize reader states with daemon */
+	rv = getReaderStates(dwContextIndex);
+	if (rv != SCARD_S_SUCCESS)
+		goto end;
+
 	dwReadersLen = 0;
 	for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
-		if ((readerStates[i])->readerID != 0)
-			dwReadersLen += strlen((readerStates[i])->readerName) + 1;
+		if (readerStates[i].readerID != 0)
+			dwReadersLen += strlen(readerStates[i].readerName) + 1;
 
 	/* for the last NULL byte */
 	dwReadersLen += 1;
@@ -3265,13 +3111,13 @@
 
 	for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++)
 	{
-		if ((readerStates[i])->readerID != 0)
+		if (readerStates[i].readerID != 0)
 		{
 			/*
 			 * Build the multi-string
 			 */
-			strcpy(buf, (readerStates[i])->readerName);
-			buf += strlen((readerStates[i])->readerName)+1;
+			strcpy(buf, readerStates[i].readerName);
+			buf += strlen(readerStates[i].readerName)+1;
 		}
 	}
 	*buf = '\0';	/* Add the last null */
@@ -3477,9 +3323,14 @@
 {
 	LONG dwContextIndex;
 	LONG rv = SCARD_S_SUCCESS;
+	uint32_t dwClientID = 0;
+	struct cancel_struct scCancelStruct;
 
 	PROFILE_START
 
+	/*
+	 * Make sure this context has been opened
+	 */
 	dwContextIndex = SCardGetContextIndice(hContext);
 	if (dwContextIndex == -1)
 		return SCARD_E_INVALID_HANDLE;
@@ -3490,9 +3341,44 @@
 	 */
 	psContextMap[dwContextIndex].contextBlockStatus = BLOCK_STATUS_RESUME;
 
-	if (StatSynchronizeContext(hContext))
-		rv = SCARD_F_INTERNAL_ERROR;
-
+	/* create a new connection to the server */
+	if (SHMClientSetupSession(&dwClientID) != 0)
+	{
+		rv = SCARD_E_NO_SERVICE;
+		goto error;
+	}
+
+	scCancelStruct.hContext = hContext;
+	scCancelStruct.rv = SCARD_S_SUCCESS;
+
+	rv = SHMMessageSendWithHeader(SCARD_CANCEL,
+		dwClientID,
+		sizeof(scCancelStruct), PCSCLITE_READ_TIMEOUT, (void *)
+		&scCancelStruct);
+
+	if (rv == -1)
+	{
+		rv = SCARD_E_NO_SERVICE;
+		goto end;
+	}
+
+	/*
+	 * Read a message from the server
+	 */
+	rv = SHMMessageReceive(&scCancelStruct, sizeof(scCancelStruct),
+		dwClientID, PCSCLITE_READ_TIMEOUT);
+
+	if (rv == -1)
+	{
+		rv = SCARD_F_COMM_ERROR;
+		goto end;
+	}
+
+	rv = scCancelStruct.rv;
+end:
+	SHMClientCloseSession(dwClientID);
+
+error:
 	PROFILE_END(rv)
 
 	return rv;
@@ -3774,11 +3660,11 @@
 	struct stat statBuffer;
 	int need_restart = 0;
 
-	rv = SYS_Stat(PCSCLITE_PUBSHM_FILE, &statBuffer);
+	rv = SYS_Stat(PCSCLITE_CSOCK_NAME, &statBuffer);
 
 	if (rv != 0)
 	{
-		Log2(PCSC_LOG_INFO, "PCSC Not Running: " PCSCLITE_PUBSHM_FILE ": %s",
+		Log2(PCSC_LOG_INFO, "PCSC Not Running: " PCSCLITE_CSOCK_NAME ": %s",
 			strerror(errno));
 		return SCARD_E_NO_SERVICE;
 	}
@@ -3819,9 +3705,6 @@
 		daemon_ctime = 0;
 		client_pid = 0;
 
-		/* reset the lib */
-		SCardUnload();
-
 		return SCARD_E_INVALID_HANDLE;
 	}
 
@@ -3863,3 +3746,19 @@
 	isExecuted = 0;
 }
 
+static LONG getReaderStates(LONG dwContextIndex)
+{
+	int32_t dwClientID = psContextMap[dwContextIndex].dwClientID;
+
+	if (-1 == SHMMessageSendWithHeader(CMD_GET_READERS_STATE, dwClientID, 0,
+		PCSCLITE_WRITE_TIMEOUT, NULL))
+		return SCARD_E_NO_SERVICE;
+
+	/* Read a message from the server */
+	if (-1 == SHMMessageReceive(&readerStates, sizeof(readerStates), dwClientID,
+		PCSCLITE_READ_TIMEOUT))
+		return SCARD_F_COMM_ERROR;
+
+	return SCARD_S_SUCCESS;
+}
+

Modified: trunk/PCSC/src/winscard_msg.c
URL: http://svn.debian.org/wsvn/pcsclite/trunk/PCSC/src/winscard_msg.c?rev=4434&op=diff
==============================================================================
--- trunk/PCSC/src/winscard_msg.c (original)
+++ trunk/PCSC/src/winscard_msg.c Tue Oct  6 09:37:51 2009
@@ -44,22 +44,6 @@
 #include "utils.h"
 
 /**
- * @brief Wrapper for the SHMMessageReceive() function.
- *
- * Called by clients to read the server responses.
- *
- * @param[out] msgStruct Message read.
- * @param[in] dwClientID Client socket handle.
- * @param[in] blockamount Timeout in milliseconds.
- *
- * @return Same error codes as SHMMessageReceive().
- */
-INTERNAL int32_t SHMClientRead(psharedSegmentMsg msgStruct, uint32_t dwClientID, int32_t blockamount)
-{
-	return SHMMessageReceive(msgStruct, sizeof(*msgStruct), dwClientID, blockamount);
-}
-
-/**
  * @brief Prepares a communication channel for the client to talk to the server.
  *
  * This is called by the application to create a socket for local IPC with the
@@ -149,28 +133,39 @@
 	int retval = 0;
 
 	/* record the time when we started */
-	time_t start = time(0);
+	struct timeval start;
 
 	/* how many bytes remains to be written */
 	size_t remaining = buffer_size;
+
+	gettimeofday(&start, NULL);
 
 	/* repeat until all data is written */
 	while (remaining > 0)
 	{
 		fd_set write_fd;
-		struct timeval timeout;
+		struct timeval timeout, now;
 		int selret;
-
-		FD_ZERO(&write_fd);
-		FD_SET(filedes, &write_fd);
-
-		timeout.tv_usec = 0;
-		if ((timeout.tv_sec = start + timeOut - time(0)) < 0)
+		long delta;
+
+		gettimeofday(&now, NULL);
+		delta = time_sub(&now, &start);
+
+		if (delta > timeOut*1000)
 		{
 			/* we already timed out */
 			retval = -1;
 			break;
 		}
+
+		/* remaining time to wait */
+		delta = timeOut*1000 - delta;
+
+		FD_ZERO(&write_fd);
+		FD_SET(filedes, &write_fd);
+
+		timeout.tv_sec = delta/1000000;
+		timeout.tv_usec = delta - timeout.tv_sec*1000000;
 
 		selret = select(filedes + 1, NULL, &write_fd, NULL, &timeout);
 
@@ -252,29 +247,40 @@
 	int retval = 0;
 
 	/* record the time when we started */
-	time_t start = time(0);
+	struct timeval start;
 
 	/* how many bytes we must read */
 	size_t remaining = buffer_size;
+
+	gettimeofday(&start, NULL);
 
 	/* repeat until we get the whole message */
 	while (remaining > 0)
 	{
 		fd_set read_fd;
-		struct timeval timeout;
+		struct timeval timeout, now;
 		int selret;
-
-		FD_ZERO(&read_fd);
-		FD_SET(filedes, &read_fd);
-
-		timeout.tv_usec = 0;
-		if ((timeout.tv_sec = start + timeOut - time(0)) < 0)
+		long delta;
+
+		gettimeofday(&now, NULL);
+		delta = time_sub(&now, &start);
+
+		if (delta > timeOut*1000)
 		{
 			/* we already timed out */
 			retval = -1;
 			break;
 		}
 
+		/* remaining time to wait */
+		delta = timeOut*1000 - delta;
+
+		FD_ZERO(&read_fd);
+		FD_SET(filedes, &read_fd);
+
+		timeout.tv_sec = delta/1000000;
+		timeout.tv_usec = delta - timeout.tv_sec*1000000;
+
 		selret = select(filedes + 1, &read_fd, NULL, NULL, &timeout);
 
 		/* try to read only when socket is readable */
@@ -297,9 +303,7 @@
 				remaining -= readed;
 			} else if (readed == 0)
 			{
-				/*
-				 * peer closed the socket
-				 */
+				/* peer closed the socket */
 				retval = -1;
 				break;
 			} else
@@ -327,9 +331,6 @@
 				break;
 			}
 
-			/* the command is extra slow so we keep waiting */
-			start = time(0);
-
 			/* you need to set the env variable PCSCLITE_DEBUG=0 since
 			 * this is logged on the client side and not on the pcscd
 			 * side*/
@@ -366,58 +367,19 @@
  *
  * @return Same error codes as SHMMessageSend().
  */
-INTERNAL int32_t WrapSHMWrite(uint32_t command, uint32_t dwClientID,
+INTERNAL int32_t SHMMessageSendWithHeader(uint32_t command, uint32_t dwClientID,
 	uint64_t size, uint32_t timeOut, void *data_void)
 {
-	char *data = data_void;
-
-	sharedSegmentMsg msgStruct;
+	struct rxHeader header;
 	int ret;
 
-	/*
-	 * Set the appropriate packet parameters
-	 */
-
-	memset(&msgStruct, 0, sizeof(msgStruct));
-	msgStruct.mtype = CMD_FUNCTION;
-	msgStruct.user_id = SYS_GetUID();
-	msgStruct.group_id = SYS_GetGID();
-	msgStruct.command = command;
-	msgStruct.date = time(NULL);
-	if ((SCARD_TRANSMIT_EXTENDED == command)
-		|| (SCARD_CONTROL_EXTENDED == command))
-	{
-		/* first block */
-		if (size > sizeof(msgStruct.data))
-			memcpy(msgStruct.data, data, sizeof(msgStruct.data));
-		else
-		{
-			memcpy(msgStruct.data, data, size);
-			memset(msgStruct.data+size, 0, sizeof(msgStruct.data)-size);
-		}
-
-		ret = SHMMessageSend(&msgStruct, sizeof(msgStruct), dwClientID,
-			timeOut);
-
-		/* do not send an empty second block */
-		if ((0 == ret) && (size > sizeof(msgStruct.data)))
-		{
-			/* second block */
-			ret = SHMMessageSend(data+sizeof(msgStruct.data),
-				size-sizeof(msgStruct.data), dwClientID, timeOut);
-		}
-	}
-	else
-	{
-		memcpy(msgStruct.data, data, size);
-
-		ret = SHMMessageSend(&msgStruct, sizeof(msgStruct), dwClientID,
-			timeOut);
-	}
-
-	if (SCARD_TRANSMIT == command)
-		/* clean APDU buffer to remove any possible PIN or secret value */
-		memset(msgStruct.data, 0, min(size, sizeof(msgStruct.data)));
+	/* header */
+	header.command = command;
+	header.size = size;
+	ret = SHMMessageSend(&header, sizeof(header), dwClientID, timeOut);
+
+	/* command */
+	ret = SHMMessageSend(data_void, size, dwClientID, timeOut);
 
 	return ret;
 }

Modified: trunk/PCSC/src/winscard_msg.h
URL: http://svn.debian.org/wsvn/pcsclite/trunk/PCSC/src/winscard_msg.h?rev=4434&op=diff
==============================================================================
--- trunk/PCSC/src/winscard_msg.h (original)
+++ trunk/PCSC/src/winscard_msg.h Tue Oct  6 09:37:51 2009
@@ -21,7 +21,7 @@
 #include <stdint.h>
 
 /** Major version of the current message protocol */
-#define PROTOCOL_VERSION_MAJOR 3
+#define PROTOCOL_VERSION_MAJOR 4
 /** Minor version of the current message protocol */
 #define PROTOCOL_VERSION_MINOR 0
 
@@ -42,44 +42,12 @@
 	typedef struct version_struct version_struct;
 
 	/**
-	 * @brief General structure for client/serve message data exchange.
-	 *
-	 * It is used in the calls of \c SHMMessageSend and \c SHMMessageReceive.
-	 * The field \c data is interpreted according to the values of the fields
-	 * \c mtype and \c command. The possible structs the \c data field can
-	 * represent are: \c version_struct \c client_struct \c establish_struct
-	 * \c release_struct \c connect_struct \c reconnect_struct
-	 * \c disconnect_struct \c begin_struct \c end_struct \c cancel_struct
-	 * \c status_struct \c transmit_struct \c control_struct \c getset_struct
-	 */
-	typedef struct rxSharedSegment
-	{
-		uint32_t mtype;		/** one of the \c pcsc_adm_commands */
-		uint32_t user_id;
-		uint32_t group_id;
-		uint32_t command;	/** one of the \c pcsc_msg_commands */
-		uint64_t date;
-		union
-		{
-			unsigned char data[PCSCLITE_MAX_MESSAGE_SIZE];
-			struct version_struct veStr;
-		};
-	}
-	sharedSegmentMsg, *psharedSegmentMsg;
-
-	/**
-	 * Command types available to use in the field \c sharedSegmentMsg.mtype.
-	 */
-	enum pcsc_adm_commands
-	{
-		CMD_FUNCTION = 0xF1,
-		CMD_FAILED = 0xF2,
-		CMD_SERVER_DIED = 0xF3,
-		CMD_CLIENT_DIED = 0xF4,
-		CMD_READER_EVENT = 0xF5,
-		CMD_SYN = 0xF6,
-		CMD_ACK = 0xF7,
-		CMD_VERSION = 0xF8	/**< version of the IPC */
+	 * @brief header structure for client/server message data exchange.
+	 */
+	struct rxHeader
+	{
+		uint32_t size;		/**< size of the message expluding this header */
+		uint32_t command;	/**< one of the \c pcsc_msg_commands */
 	};
 
 	/**
@@ -100,11 +68,13 @@
 		SCARD_STATUS = 0x0B,			/**< used by SCardStatus() */
 		SCARD_GET_STATUS_CHANGE = 0x0C,	/**< used by SCardGetStatusChange() */
 		SCARD_CANCEL = 0x0D,			/**< used by SCardCancel() */
-		SCARD_CANCEL_TRANSACTION = 0x0E,
+		SCARD_CANCEL_TRANSACTION = 0x0E,	/**< used by SCardCancelTransaction() */
 		SCARD_GET_ATTRIB = 0x0F,		/**< used by SCardGetAttrib() */
 		SCARD_SET_ATTRIB = 0x10,		/**< used by SCardSetAttrib() */
-		SCARD_TRANSMIT_EXTENDED = 0x11,	/**< used by SCardTransmit() */
-		SCARD_CONTROL_EXTENDED = 0x12	/**< used by SCardControl() */
+		CMD_VERSION = 0x11,				/**< get the client/server protocol version */
+		CMD_GET_READERS_STATE = 0x12,	/**< get the readers state */
+		CMD_WAIT_READER_STATE_CHANGE = 0x13,	/**< wait for a reader state change */
+		CMD_STOP_WAITING_READER_STATE_CHANGE = 0x14	/**< stop waiting for a reader state change */
 	};
 
 	struct client_struct
@@ -225,10 +195,22 @@
 	 */
 	struct cancel_struct
 	{
-		int32_t hCard;
+		int32_t hContext;
 		uint32_t rv;
 	};
 	typedef struct cancel_struct cancel_struct;
+
+	/**
+	 * @brief contained in \ref SCARD_CANCEL_TRANSACTION Messages.
+	 *
+	 * These data are passed throw the field \c sharedSegmentMsg.data.
+	 */
+	struct cancel_transaction_struct
+	{
+		int32_t hCard;
+		uint32_t rv;
+	};
+	typedef struct cancel_transaction_struct cancel_transaction_struct;
 
 	/**
 	 * @brief contained in \ref SCARD_STATUS Messages.
@@ -258,35 +240,13 @@
 		int32_t hCard;
 		uint32_t ioSendPciProtocol;
 		uint32_t ioSendPciLength;
-		uint8_t pbSendBuffer[MAX_BUFFER_SIZE];
-		uint32_t cbSendLength;
-		uint32_t ioRecvPciProtocol;
-		uint32_t ioRecvPciLength;
-		uint8_t pbRecvBuffer[MAX_BUFFER_SIZE];
-		uint32_t pcbRecvLength;
-		uint32_t rv;
-	};
-	typedef struct transmit_struct transmit_struct;
-
-	/**
-	 * @brief contained in \ref SCARD_TRANSMIT_EXTENDED Messages.
-	 *
-	 * These data are passed throw the field \c sharedSegmentMsg.data.
-	 */
-	struct transmit_struct_extended
-	{
-		int32_t hCard;
-		uint32_t ioSendPciProtocol;
-		uint32_t ioSendPciLength;
 		uint32_t cbSendLength;
 		uint32_t ioRecvPciProtocol;
 		uint32_t ioRecvPciLength;
 		uint32_t pcbRecvLength;
 		uint32_t rv;
-		uint64_t size;
-		uint8_t data[1];
-	};
-	typedef struct transmit_struct_extended transmit_struct_extended;
+	};
+	typedef struct transmit_struct transmit_struct;
 
 	/**
 	 * @brief contained in \ref SCARD_CONTROL Messages.
@@ -294,24 +254,6 @@
 	 * These data are passed throw the field \c sharedSegmentMsg.data.
 	 */
 	struct control_struct
-	{
-		int32_t hCard;
-		uint32_t dwControlCode;
-		uint8_t pbSendBuffer[MAX_BUFFER_SIZE];
-		uint32_t cbSendLength;
-		uint8_t pbRecvBuffer[MAX_BUFFER_SIZE];
-		uint32_t cbRecvLength;
-		uint32_t dwBytesReturned;
-		uint32_t rv;
-	};
-	typedef struct control_struct control_struct;
-
-	/**
-	 * @brief contained in \ref SCARD_CONTROL_EXTENDED Messages.
-	 *
-	 * These data are passed throw the field \c sharedSegmentMsg.data.
-	 */
-	struct control_struct_extended
 	{
 		int32_t hCard;
 		uint32_t dwControlCode;
@@ -319,8 +261,6 @@
 		uint32_t cbRecvLength;
 		uint32_t dwBytesReturned;
 		uint32_t rv;
-		uint64_t size;
-		uint8_t data[1];
 	};
 	typedef struct control_struct_extended control_struct_extended;
 
@@ -343,17 +283,15 @@
 	 * Now some function definitions
 	 */
 
-	int32_t SHMClientRead(psharedSegmentMsg, uint32_t, int32_t);
 	int32_t SHMClientSetupSession(uint32_t *);
 	int32_t SHMClientCloseSession(uint32_t);
 	int32_t SHMInitializeCommonSegment(void);
-	int32_t SHMProcessEventsContext(uint32_t, /*@out@*/ psharedSegmentMsg);
 	int32_t SHMProcessEventsServer(/*@out@*/ uint32_t *);
 	int32_t SHMMessageSend(void *buffer, uint64_t buffer_size, int32_t filedes,
 		int32_t blockAmount);
 	int32_t SHMMessageReceive(/*@out@*/ void *buffer, uint64_t buffer_size,
 		int32_t filedes, int32_t blockAmount);
-	int32_t WrapSHMWrite(uint32_t command, uint32_t dwClientID, uint64_t size,
+	int32_t SHMMessageSendWithHeader(uint32_t command, uint32_t dwClientID, uint64_t size,
 		uint32_t blockAmount, void *data);
 	void SHMCleanupSharedSegment(int32_t, const char *);
 

Modified: trunk/PCSC/src/winscard_msg_srv.c
URL: http://svn.debian.org/wsvn/pcsclite/trunk/PCSC/src/winscard_msg_srv.c?rev=4434&op=diff
==============================================================================
--- trunk/PCSC/src/winscard_msg_srv.c (original)
+++ trunk/PCSC/src/winscard_msg_srv.c Tue Oct  6 09:37:51 2009
@@ -49,29 +49,6 @@
 extern char AraKiri;
 extern char ReCheckSerialReaders;
 
-static const char *CommandsText[] = {
-	"CMD_VERSION",	/* mtype = 0xF8 and command = 0x00 */
-	"ESTABLISH_CONTEXT",	/* mtype = 0xF1 */
-	"RELEASE_CONTEXT",
-	"LIST_READERS",
-	"CONNECT",
-	"RECONNECT",
-	"DISCONNECT",
-	"BEGIN_TRANSACTION",
-	"END_TRANSACTION",
-	"TRANSMIT",
-	"CONTROL",
-	"STATUS",
-	"GET_STATUS_CHANGE",
-	"CANCEL",
-	"CANCEL_TRANSACTION",
-	"GET_ATTRIB",
-	"SET_ATTRIB",
-	"TRANSMIT_EXTENDED",
-	"CONTROL_EXTENDED",
-	"NULL"
-};
-
 /**
  * @brief Accepts a Client connection.
  *
@@ -82,14 +59,12 @@
  * @return Error code.
  * @retval 0 Success.
  * @retval -1 Can not establish the connection.
- * @retval -1 Can not set the connection to non-blocking mode.
  */
 static int SHMProcessCommonChannelRequest(/*@out@*/ uint32_t *pdwClientID)
 {
 	socklen_t clnt_len;
 	int new_sock;
 	struct sockaddr_un clnt_addr;
-	int one;
 
 	clnt_len = sizeof(clnt_addr);
 
@@ -102,16 +77,6 @@
 	}
 
 	*pdwClientID = new_sock;
-
-	one = 1;
-	if (ioctl(*pdwClientID, FIONBIO, &one) < 0)
-	{
-		Log2(PCSC_LOG_CRITICAL, "Error: cannot set socket nonblocking: %s",
-			strerror(errno));
-		(void)SYS_CloseFile(*pdwClientID);
-		*pdwClientID = -1;
-		return -1;
-	}
 
 	return 0;
 }
@@ -184,7 +149,7 @@
  * @return Error code.
  * @retval 0 Success.
  * @retval -1 Error accessing the communication channel.
- * @retval -1 Can not set the connection to non-blocking mode.
+ * @retval -2 EINTR
  * @retval 2 Timeout.
  */
 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
@@ -242,82 +207,14 @@
 			Log2(PCSC_LOG_ERROR,
 				"error in SHMProcessCommonChannelRequest: %d", *pdwClientID);
 			return -1;
-		} else
-		{
-			Log2(PCSC_LOG_DEBUG,
-				"SHMProcessCommonChannelRequest detects: %d", *pdwClientID);
-			return 0;
 		}
 	}
-
-	return -1;
+	else
+		return -1;
+
+	Log2(PCSC_LOG_DEBUG,
+		"SHMProcessCommonChannelRequest detects: %d", *pdwClientID);
+
+	return 0;
 }
 
-/**
- * @brief
- *
- * Called by \c ContextThread().
- */
-INTERNAL int32_t SHMProcessEventsContext(uint32_t dwClientID,
-	psharedSegmentMsg msgStruct)
-{
-	fd_set read_fd;
-	int selret, rv;
-#ifdef DO_TIMEOUT
-	struct timeval tv;
-
-	tv.tv_sec = 1;
-	tv.tv_usec = 0;
-#endif
-
-	FD_ZERO(&read_fd);
-	FD_SET(dwClientID, &read_fd);
-
-	selret = select(dwClientID + 1, &read_fd, (fd_set *) NULL,
-		(fd_set *) NULL,
-#ifdef DO_TIMEOUT
-		&tv
-#else
-		NULL
-#endif
-		);
-
-	if (selret < 0)
-	{
-		Log2(PCSC_LOG_ERROR, "select returns with failure: %s",
-			strerror(errno));
-		return -1;
-	}
-
-	if (selret == 0)
-		/* timeout */
-		return 2;
-
-	if (FD_ISSET(dwClientID, &read_fd))
-	{
-		/*
-		 * Return the current handle
-		 */
-		rv = SHMMessageReceive(msgStruct, sizeof(*msgStruct), dwClientID,
-				       PCSCLITE_SERVER_ATTEMPTS);
-
-		if (rv == -1)
-		{	/* The client has died */
-			Log2(PCSC_LOG_DEBUG, "Client has disappeared: %d", dwClientID);
-			msgStruct->mtype = CMD_CLIENT_DIED;
-			msgStruct->command = 0;
-			(void)SYS_CloseFile(dwClientID);
-
-			return 0;
-		}
-
-		/*
-		 * Set the identifier handle
-		 */
-		Log3(PCSC_LOG_DEBUG, "command %s received by client %d", CommandsText[msgStruct->command], dwClientID);
-		return 1;
-	}
-
-	return -1;
-}
-

Modified: trunk/PCSC/src/winscard_svc.c
URL: http://svn.debian.org/wsvn/pcsclite/trunk/PCSC/src/winscard_svc.c?rev=4434&op=diff
==============================================================================
--- trunk/PCSC/src/winscard_svc.c (original)
+++ trunk/PCSC/src/winscard_svc.c Tue Oct  6 09:37:51 2009
@@ -33,6 +33,7 @@
 #include "sys_generic.h"
 #include "thread_generic.h"
 #include "readerfactory.h"
+#include "eventhandler.h"
 
 /**
  * @brief Represents an Application Context on the Server side.
@@ -45,12 +46,10 @@
 	uint32_t hCard[PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS];
 	uint32_t dwClientID;			/**< Connection ID used to reference the Client. */
 	PCSCLITE_THREAD_T pthThread;		/**< Event polling thread's ID */
-	sharedSegmentMsg msgStruct;		/**< Msg sent by the Client */
 	int protocol_major, protocol_minor;	/**< Protocol number agreed between client and server*/
 } psContext[PCSCLITE_MAX_APPLICATIONS_CONTEXTS];
 
 static LONG MSGCheckHandleAssociation(SCARDHANDLE, DWORD);
-static LONG MSGFunctionDemarshall(psharedSegmentMsg, DWORD);
 static LONG MSGAddContext(SCARDCONTEXT, DWORD);
 static LONG MSGRemoveContext(SCARDCONTEXT, DWORD);
 static LONG MSGAddHandle(SCARDCONTEXT, SCARDHANDLE, DWORD);
@@ -58,6 +57,8 @@
 static LONG MSGCleanupClient(DWORD);
 
 static void ContextThread(LPVOID pdwIndex);
+
+extern READER_STATE readerStates[PCSCLITE_MAX_READERS_CONTEXTS];
 
 LONG ContextsInitialize(void)
 {
@@ -131,559 +132,525 @@
  * @param[in] dwIndex Index of an avaiable Application Context slot in
  * \c psContext.
  */
+static const char *CommandsText[] = {
+	"NULL",
+	"ESTABLISH_CONTEXT",	/* 0x01 */
+	"RELEASE_CONTEXT",
+	"LIST_READERS",
+	"CONNECT",
+	"RECONNECT",			/* 0x05 */
+	"DISCONNECT",
+	"BEGIN_TRANSACTION",
+	"END_TRANSACTION",
+	"TRANSMIT",
+	"CONTROL",				/* 0x0A */
+	"STATUS",
+	"GET_STATUS_CHANGE",
+	"CANCEL",
+	"CANCEL_TRANSACTION",
+	"GET_ATTRIB",			/* 0x0F */
+	"SET_ATTRIB",
+	"CMD_VERSION",
+	"CMD_GET_READERS_STATE",
+	"CMD_WAIT_READER_STATE_CHANGE",
+	"CMD_STOP_WAITING_READER_STATE_CHANGE",	/* 0x14 */
+	"NULL"
+};
+
+#define READ_BODY(v) \
+	if (header.size != sizeof(v)) {printf("%d %d\n", header.size, sizeof(v)); goto wrong_length;} \
+	ret = SHMMessageReceive(&v, sizeof(v), filedes, PCSCLITE_READ_TIMEOUT); \
+	if (-1 == ret) { Log2(PCSC_LOG_DEBUG, "Client die: %d", filedes); goto exit; }
+
+#define WRITE_BODY(v) \
+	ret = SHMMessageSend(&v, sizeof(v), filedes, PCSCLITE_WRITE_TIMEOUT);
+
 static void ContextThread(LPVOID dwIndex)
 {
-	LONG rv;
-	sharedSegmentMsg msgStruct;
 	DWORD dwContextIndex = (DWORD)dwIndex;
+	int32_t filedes = psContext[dwContextIndex].dwClientID;
 
 	Log2(PCSC_LOG_DEBUG, "Thread is started: %d",
 		psContext[dwContextIndex].dwClientID);
 
 	while (1)
 	{
-		switch (rv = SHMProcessEventsContext(psContext[dwContextIndex].dwClientID, &msgStruct))
-		{
-		case 0:
-			if (msgStruct.mtype == CMD_CLIENT_DIED)
-			{
-				/*
-				 * Clean up the dead client
-				 */
-				Log2(PCSC_LOG_DEBUG, "Client die: %d",
-					psContext[dwContextIndex].dwClientID);
-				(void)MSGCleanupClient(dwContextIndex);
-				(void)SYS_ThreadExit((LPVOID) NULL);
-			}
-			break;
-
-		case 1:
-			if (msgStruct.mtype == CMD_FUNCTION)
-			{
-				/*
-				 * Command must be found
-				 */
-				rv = MSGFunctionDemarshall(&msgStruct, dwContextIndex);
-				if (rv)
+		struct rxHeader header;
+		int32_t ret = SHMMessageReceive(&header, sizeof(header), filedes, PCSCLITE_READ_TIMEOUT);
+
+		if (-1 == ret)
+		{
+			/* Clean up the dead client */
+			Log2(PCSC_LOG_DEBUG, "Client die: %d", filedes);
+			goto exit;
+		}
+
+		Log2(PCSC_LOG_DEBUG, "Received command: %s", CommandsText[header.command]);
+
+		switch (header.command)
+		{
+			/* pcsc-lite client/server protocol version */
+			case CMD_VERSION:
+			{
+				struct version_struct veStr;
+
+				READ_BODY(veStr)
+
+				/* get the client protocol version */
+				psContext[dwContextIndex].protocol_major = veStr.major;
+				psContext[dwContextIndex].protocol_minor = veStr.minor;
+
+				Log3(PCSC_LOG_DEBUG,
+						"Client is protocol version %d:%d",
+						veStr.major, veStr.minor);
+
+				veStr.rv = SCARD_S_SUCCESS;
+
+				/* client is newer than server */
+				if ((veStr.major > PROTOCOL_VERSION_MAJOR)
+						|| (veStr.major == PROTOCOL_VERSION_MAJOR
+							&& veStr.minor > PROTOCOL_VERSION_MINOR))
 				{
-					Log2(PCSC_LOG_DEBUG, "MSGFunctionDemarshall failed: %d",
-						rv);
-					(void)SHMClientCloseSession(psContext[dwContextIndex].dwClientID);
-					(void)MSGCleanupClient(dwContextIndex);
-					(void)SYS_ThreadExit((LPVOID) NULL);
-				}
-
-				/* the SCARD_TRANSMIT_EXTENDED anwser is already sent by
-				 * MSGFunctionDemarshall */
-				if ((msgStruct.command != SCARD_TRANSMIT_EXTENDED)
-					&& (msgStruct.command != SCARD_CONTROL_EXTENDED))
-					rv = SHMMessageSend(&msgStruct, sizeof(msgStruct),
-						psContext[dwContextIndex].dwClientID,
-						PCSCLITE_SERVER_ATTEMPTS);
-			}
-			else
-				/* pcsc-lite client/server protocol version */
-				if (msgStruct.mtype == CMD_VERSION)
-				{
-					version_struct *veStr;
-					veStr = &msgStruct.veStr;
-
-					/* get the client protocol version */
-					psContext[dwContextIndex].protocol_major = veStr->major;
-					psContext[dwContextIndex].protocol_minor = veStr->minor;
-
-					Log3(PCSC_LOG_DEBUG,
-						"Client is protocol version %d:%d",
-						veStr->major, veStr->minor);
-
-					veStr->rv = SCARD_S_SUCCESS;
-
-					/* client is newer than server */
-					if ((veStr->major > PROTOCOL_VERSION_MAJOR)
-						|| (veStr->major == PROTOCOL_VERSION_MAJOR
-							&& veStr->minor > PROTOCOL_VERSION_MINOR))
-					{
-						Log3(PCSC_LOG_CRITICAL,
+					Log3(PCSC_LOG_CRITICAL,
 							"Client protocol is too new %d:%d",
-							veStr->major, veStr->minor);
-						Log3(PCSC_LOG_CRITICAL,
+							veStr.major, veStr.minor);
+					Log3(PCSC_LOG_CRITICAL,
 							"Server protocol is %d:%d",
 							PROTOCOL_VERSION_MAJOR, PROTOCOL_VERSION_MINOR);
-						veStr->rv = SCARD_E_NO_SERVICE;
+					veStr.rv = SCARD_E_NO_SERVICE;
+				}
+
+				/* set the server protocol version */
+				veStr.major = PROTOCOL_VERSION_MAJOR;
+				veStr.minor = PROTOCOL_VERSION_MINOR;
+
+				/* send back the response */
+				WRITE_BODY(veStr)
+			}
+			break;
+
+			case CMD_GET_READERS_STATE:
+			{
+				/* nothing to read */
+
+				/* dump the readers state */
+				ret = SHMMessageSend(readerStates, sizeof(readerStates), filedes, PCSCLITE_WRITE_TIMEOUT);
+			}
+			break;
+
+			case CMD_WAIT_READER_STATE_CHANGE:
+			{
+				struct wait_reader_state_change waStr;
+
+				READ_BODY(waStr)
+
+				/* add the client fd to the list */
+				EHRegisterClientForEvent(filedes);
+
+				/* We do not send anything here.
+				 * Either the client will timeout or the server will
+				 * answer if an event occurs */
+			}
+			break;
+
+			case CMD_STOP_WAITING_READER_STATE_CHANGE:
+			{
+				struct wait_reader_state_change waStr;
+
+				READ_BODY(waStr)
+
+				/* add the client fd to the list */
+				waStr.rv = EHUnregisterClientForEvent(filedes);
+
+				WRITE_BODY(waStr)
+			}
+			break;
+
+			case SCARD_ESTABLISH_CONTEXT:
+			{
+				struct establish_struct esStr;
+				SCARDCONTEXT hContext;
+
+				READ_BODY(esStr)
+
+				hContext = esStr.hContext;
+				esStr.rv = SCardEstablishContext(esStr.dwScope, 0, 0, &hContext);
+				esStr.hContext = hContext;
+
+				if (esStr.rv == SCARD_S_SUCCESS)
+					esStr.rv =
+						MSGAddContext(esStr.hContext, dwContextIndex);
+
+				WRITE_BODY(esStr)
+			}
+			break;
+
+			case SCARD_RELEASE_CONTEXT:
+			{
+				struct release_struct reStr;
+
+				READ_BODY(reStr)
+
+				reStr.rv = SCardReleaseContext(reStr.hContext);
+
+				if (reStr.rv == SCARD_S_SUCCESS)
+					reStr.rv =
+						MSGRemoveContext(reStr.hContext, dwContextIndex);
+
+				WRITE_BODY(reStr)
+			}
+			break;
+
+			case SCARD_CONNECT:
+			{
+				struct connect_struct coStr;
+				SCARDHANDLE hCard;
+				DWORD dwActiveProtocol;
+
+				READ_BODY(coStr)
+
+				hCard = coStr.hCard;
+				dwActiveProtocol = coStr.dwActiveProtocol;
+
+				coStr.rv = SCardConnect(coStr.hContext, coStr.szReader,
+						coStr.dwShareMode, coStr.dwPreferredProtocols,
+						&hCard, &dwActiveProtocol);
+
+				coStr.hCard = hCard;
+				coStr.dwActiveProtocol = dwActiveProtocol;
+
+				if (coStr.rv == SCARD_S_SUCCESS)
+					coStr.rv =
+						MSGAddHandle(coStr.hContext, coStr.hCard, dwContextIndex);
+
+				WRITE_BODY(coStr)
+			}
+			break;
+
+			case SCARD_RECONNECT:
+			{
+				struct reconnect_struct rcStr;
+				DWORD dwActiveProtocol;
+
+				READ_BODY(rcStr)
+
+				if (MSGCheckHandleAssociation(rcStr.hCard, dwContextIndex))
+					goto exit;
+
+				rcStr.rv = SCardReconnect(rcStr.hCard, rcStr.dwShareMode,
+						rcStr.dwPreferredProtocols,
+						rcStr.dwInitialization, &dwActiveProtocol);
+				rcStr.dwActiveProtocol = dwActiveProtocol;
+
+				WRITE_BODY(rcStr)
+			}
+			break;
+
+			case SCARD_DISCONNECT:
+			{
+				struct disconnect_struct diStr;
+				LONG rv;
+
+				READ_BODY(diStr)
+
+				rv = MSGCheckHandleAssociation(diStr.hCard, dwContextIndex);
+				if (0 == rv)
+				{
+					diStr.rv = SCardDisconnect(diStr.hCard, diStr.dwDisposition);
+
+					if (SCARD_S_SUCCESS == diStr.rv)
+						diStr.rv =
+							MSGRemoveHandle(diStr.hCard, dwContextIndex);
+				}
+
+				WRITE_BODY(diStr)
+			}
+			break;
+
+			case SCARD_BEGIN_TRANSACTION:
+			{
+				struct begin_struct beStr;
+				LONG rv;
+
+				READ_BODY(beStr)
+
+				rv = MSGCheckHandleAssociation(beStr.hCard, dwContextIndex);
+				if (0 == rv)
+					beStr.rv = SCardBeginTransaction(beStr.hCard);
+
+				WRITE_BODY(beStr)
+			}
+			break;
+
+			case SCARD_END_TRANSACTION:
+			{
+				struct end_struct enStr;
+				LONG rv;
+
+				READ_BODY(enStr)
+
+				rv = MSGCheckHandleAssociation(enStr.hCard, dwContextIndex);
+				if (0 == rv)
+					enStr.rv =
+						SCardEndTransaction(enStr.hCard, enStr.dwDisposition);
+
+				WRITE_BODY(enStr)
+			}
+			break;
+
+			case SCARD_CANCEL_TRANSACTION:
+			{
+				struct cancel_transaction_struct caStr;
+				LONG rv;
+
+				READ_BODY(caStr)
+
+				rv = MSGCheckHandleAssociation(caStr.hCard, dwContextIndex);
+				if (0 == rv)
+					caStr.rv = SCardCancelTransaction(caStr.hCard);
+
+				WRITE_BODY(caStr)
+			}
+			break;
+
+			case SCARD_CANCEL:
+			{
+				struct cancel_struct caStr;
+				uint32_t fd = 0;
+				int i;
+
+				READ_BODY(caStr)
+
+				/* find the client */
+				for (i=0; i<PCSCLITE_MAX_APPLICATIONS_CONTEXTS; i++)
+				{
+					if (psContext[i].hContext == caStr.hContext)
+					{
+						fd = psContext[i].dwClientID;
+						break;
 					}
-
-					/* set the server protocol version */
-					veStr->major = PROTOCOL_VERSION_MAJOR;
-					veStr->minor = PROTOCOL_VERSION_MINOR;
-
-					/* send back the response */
-					rv = SHMMessageSend(&msgStruct, sizeof(msgStruct),
-						psContext[dwContextIndex].dwClientID,
-					    PCSCLITE_SERVER_ATTEMPTS);
 				}
+
+				if (fd)
+					caStr.rv = MSGSignalClient(fd, SCARD_E_CANCELLED);
 				else
-					continue;
-
-			break;
-
-		case 2:
-			/*
-			 * timeout in SHMProcessEventsContext(): do nothing
-			 * this is used to catch the Ctrl-C signal at some time when
-			 * nothing else happens
-			 */
-			break;
-
-		case -1:
-			Log1(PCSC_LOG_ERROR, "Error in SHMProcessEventsContext");
-			break;
-
-		default:
-			Log2(PCSC_LOG_ERROR,
-				"SHMProcessEventsContext unknown retval: %d", rv);
-			break;
+					caStr.rv = SCARD_E_INVALID_VALUE;
+
+				WRITE_BODY(caStr)
+			}
+			break;
+
+			case SCARD_STATUS:
+			{
+				struct status_struct stStr;
+				LONG rv;
+
+				READ_BODY(stStr)
+
+				rv = MSGCheckHandleAssociation(stStr.hCard, dwContextIndex);
+				if (0 == rv)
+				{
+					DWORD cchReaderLen;
+					DWORD dwState;
+					DWORD dwProtocol;
+					DWORD cbAtrLen;
+
+					cchReaderLen = stStr.pcchReaderLen;
+					dwState = stStr.dwState;
+					dwProtocol = stStr.dwProtocol;
+					cbAtrLen = stStr.pcbAtrLen;
+
+					/* avoids buffer overflow */
+					if ((cchReaderLen > sizeof(stStr.mszReaderNames))
+						|| (cbAtrLen > sizeof(stStr.pbAtr)))
+					{
+						stStr.rv = SCARD_E_INSUFFICIENT_BUFFER ;
+					}
+					else
+					{
+						stStr.rv = SCardStatus(stStr.hCard,
+							stStr.mszReaderNames,
+							&cchReaderLen, &dwState,
+							&dwProtocol, stStr.pbAtr, &cbAtrLen);
+
+						stStr.pcchReaderLen = cchReaderLen;
+						stStr.dwState = dwState;
+						stStr.dwProtocol = dwProtocol;
+						stStr.pcbAtrLen = cbAtrLen;
+					}
+				}
+
+				WRITE_BODY(stStr)
+			}
+			break;
+
+			case SCARD_TRANSMIT:
+			{
+				struct transmit_struct trStr;
+				unsigned char pbSendBuffer[MAX_BUFFER_SIZE_EXTENDED];
+				unsigned char pbRecvBuffer[MAX_BUFFER_SIZE_EXTENDED];
+				SCARD_IO_REQUEST ioSendPci;
+				SCARD_IO_REQUEST ioRecvPci;
+				DWORD cbRecvLength;
+
+				READ_BODY(trStr)
+
+				if (MSGCheckHandleAssociation(trStr.hCard, dwContextIndex))
+					goto exit;
+
+				/* avoids buffer overflow */
+				if ((trStr.pcbRecvLength > sizeof(pbRecvBuffer))
+					|| (trStr.cbSendLength > sizeof(pbSendBuffer)))
+					goto exit;
+
+				/* read sent buffer */
+				ret = SHMMessageReceive(pbSendBuffer, trStr.cbSendLength,
+					filedes, PCSCLITE_READ_TIMEOUT);
+				if (-1 == ret)
+				{
+					Log2(PCSC_LOG_DEBUG, "Client die: %d", filedes);
+					goto exit;
+				}
+
+				ioSendPci.dwProtocol = trStr.ioSendPciProtocol;
+				ioSendPci.cbPciLength = trStr.ioSendPciLength;
+				ioRecvPci.dwProtocol = trStr.ioRecvPciProtocol;
+				ioRecvPci.cbPciLength = trStr.ioRecvPciLength;
+				cbRecvLength = trStr.pcbRecvLength;
+
+				trStr.rv = SCardTransmit(trStr.hCard, &ioSendPci,
+					pbSendBuffer, trStr.cbSendLength, &ioRecvPci,
+					pbRecvBuffer, &cbRecvLength);
+
+				trStr.ioSendPciProtocol = ioSendPci.dwProtocol;
+				trStr.ioSendPciLength = ioSendPci.cbPciLength;
+				trStr.ioRecvPciProtocol = ioRecvPci.dwProtocol;
+				trStr.ioRecvPciLength = ioRecvPci.cbPciLength;
+				trStr.pcbRecvLength = cbRecvLength;
+
+				WRITE_BODY(trStr)
+
+				/* write received buffer */
+				if (SCARD_S_SUCCESS == trStr.rv)
+					ret = SHMMessageSend(pbRecvBuffer, cbRecvLength,
+						filedes, PCSCLITE_WRITE_TIMEOUT);
+			}
+			break;
+
+			case SCARD_CONTROL:
+			{
+				struct control_struct ctStr;
+				unsigned char pbSendBuffer[MAX_BUFFER_SIZE_EXTENDED];
+				unsigned char pbRecvBuffer[MAX_BUFFER_SIZE_EXTENDED];
+				DWORD dwBytesReturned;
+
+				READ_BODY(ctStr)
+
+				if (MSGCheckHandleAssociation(ctStr.hCard, dwContextIndex))
+					goto exit;
+
+				/* avoids buffer overflow */
+				if ((ctStr.cbRecvLength > sizeof(pbRecvBuffer))
+					|| (ctStr.cbSendLength > sizeof(pbSendBuffer)))
+				{
+					goto exit;
+				}
+
+				/* read sent buffer */
+				ret = SHMMessageReceive(pbSendBuffer, ctStr.cbSendLength,
+					filedes, PCSCLITE_READ_TIMEOUT);
+				if (-1 == ret)
+				{
+					Log2(PCSC_LOG_DEBUG, "Client die: %d", filedes);
+					goto exit;
+				}
+
+				dwBytesReturned = ctStr.dwBytesReturned;
+
+				ctStr.rv = SCardControl(ctStr.hCard, ctStr.dwControlCode,
+					pbSendBuffer, ctStr.cbSendLength,
+					pbRecvBuffer, ctStr.cbRecvLength,
+					&dwBytesReturned);
+
+				ctStr.dwBytesReturned = dwBytesReturned;
+
+				WRITE_BODY(ctStr)
+
+				/* write received buffer */
+				if (SCARD_S_SUCCESS == ctStr.rv)
+					ret = SHMMessageSend(pbRecvBuffer, dwBytesReturned,
+						filedes, PCSCLITE_WRITE_TIMEOUT);
+			}
+			break;
+
+			case SCARD_GET_ATTRIB:
+			{
+				struct getset_struct gsStr;
+				DWORD cbAttrLen;
+
+				READ_BODY(gsStr)
+
+				if (MSGCheckHandleAssociation(gsStr.hCard, dwContextIndex))
+					goto exit;
+
+				/* avoids buffer overflow */
+				if (gsStr.cbAttrLen > sizeof(gsStr.pbAttr))
+					goto buffer_overflow;
+
+				cbAttrLen = gsStr.cbAttrLen;
+
+				gsStr.rv = SCardGetAttrib(gsStr.hCard, gsStr.dwAttrId,
+						gsStr.pbAttr, &cbAttrLen);
+
+				gsStr.cbAttrLen = cbAttrLen;
+
+				WRITE_BODY(gsStr)
+			}
+			break;
+
+			case SCARD_SET_ATTRIB:
+			{
+				struct getset_struct gsStr;
+
+				READ_BODY(gsStr)
+
+				if (MSGCheckHandleAssociation(gsStr.hCard, dwContextIndex))
+					goto buffer_overflow;
+
+				/* avoids buffer overflow */
+				if (gsStr.cbAttrLen > sizeof(gsStr.pbAttr))
+					goto buffer_overflow;
+
+				gsStr.rv = SCardSetAttrib(gsStr.hCard, gsStr.dwAttrId,
+					gsStr.pbAttr, gsStr.cbAttrLen);
+
+				WRITE_BODY(gsStr)
+			}
+			break;
+
+			default:
+				Log2(PCSC_LOG_CRITICAL, "Unknown command: %d", header.command);
+				goto exit;
+		}
+
+		/* SHMMessageSend() failed */
+		if (-1 == ret)
+		{
+			/* Clean up the dead client */
+			Log2(PCSC_LOG_DEBUG, "Client die: %d", filedes);
+			goto exit;
 		}
 	}
-}
-
-/**
- * @brief Find out which message was sent by the Client and execute the right task.
- *
- * According to the command type sent by the client (\c pcsc_msg_commands),
- * cast the message data to the correct struct so that is can be demarshalled.
- * Then call the appropriate function to handle the request.
- *
- * Possible structs are: \c establish_struct \c release_struct
- * \c connect_struct \c reconnect_struct \c disconnect_struct \c begin_struct
- * \c cancel_struct \c end_struct \c status_struct \c transmit_struct
- * \c control_struct \c getset_struct.
- *
- * @param[in] msgStruct Message to be demarshalled and executed.
- * @param[in] dwContextIndex
- */
-static LONG MSGFunctionDemarshall(psharedSegmentMsg msgStruct,
-	DWORD dwContextIndex)
-{
-	LONG rv;
-	establish_struct *esStr;
-	release_struct *reStr;
-	connect_struct *coStr;
-	reconnect_struct *rcStr;
-	disconnect_struct *diStr;
-	begin_struct *beStr;
-	cancel_struct *caStr;
-	end_struct *enStr;
-	status_struct *stStr;
-	transmit_struct *trStr;
-	control_struct *ctStr;
-	getset_struct *gsStr;
-
-	SCARDCONTEXT hContext;
-	SCARDHANDLE hCard;
-	DWORD dwActiveProtocol;
-
-	DWORD cchReaderLen;
-	DWORD dwState;
-	DWORD dwProtocol;
-	DWORD cbAtrLen;
-	DWORD cbRecvLength;
-	DWORD dwBytesReturned;
-	DWORD cbAttrLen;
-
-	SCARD_IO_REQUEST ioSendPci;
-	SCARD_IO_REQUEST ioRecvPci;
-
-	/*
-	 * Zero out everything
-	 */
-	rv = 0;
-	switch (msgStruct->command)
-	{
-
-	case SCARD_ESTABLISH_CONTEXT:
-		esStr = ((establish_struct *) msgStruct->data);
-
-		hContext = esStr->hContext;
-		esStr->rv = SCardEstablishContext(esStr->dwScope, 0, 0, &hContext);
-		esStr->hContext = hContext;
-
-		if (esStr->rv == SCARD_S_SUCCESS)
-			esStr->rv =
-				MSGAddContext(esStr->hContext, dwContextIndex);
-		break;
-
-	case SCARD_RELEASE_CONTEXT:
-		reStr = ((release_struct *) msgStruct->data);
-		reStr->rv = SCardReleaseContext(reStr->hContext);
-
-		if (reStr->rv == SCARD_S_SUCCESS)
-			reStr->rv =
-				MSGRemoveContext(reStr->hContext, dwContextIndex);
-
-		break;
-
-	case SCARD_CONNECT:
-		coStr = ((connect_struct *) msgStruct->data);
-
-		hCard = coStr->hCard;
-		dwActiveProtocol = coStr->dwActiveProtocol;
-
-		coStr->rv = SCardConnect(coStr->hContext, coStr->szReader,
-			coStr->dwShareMode, coStr->dwPreferredProtocols,
-			&hCard, &dwActiveProtocol);
-
-		coStr->hCard = hCard;
-		coStr->dwActiveProtocol = dwActiveProtocol;
-
-		if (coStr->rv == SCARD_S_SUCCESS)
-			coStr->rv =
-				MSGAddHandle(coStr->hContext, coStr->hCard, dwContextIndex);
-
-		break;
-
-	case SCARD_RECONNECT:
-		rcStr = ((reconnect_struct *) msgStruct->data);
-		rv = MSGCheckHandleAssociation(rcStr->hCard, dwContextIndex);
-		if (rv != 0) return rv;
-
-		rcStr->rv = SCardReconnect(rcStr->hCard, rcStr->dwShareMode,
-			rcStr->dwPreferredProtocols,
-			rcStr->dwInitialization, &dwActiveProtocol);
-		rcStr->dwActiveProtocol = dwActiveProtocol;
-		break;
-
-	case SCARD_DISCONNECT:
-		diStr = ((disconnect_struct *) msgStruct->data);
-		rv = MSGCheckHandleAssociation(diStr->hCard, dwContextIndex);
-		if (rv != 0) return rv;
-		diStr->rv = SCardDisconnect(diStr->hCard, diStr->dwDisposition);
-
-		if (diStr->rv == SCARD_S_SUCCESS)
-			diStr->rv =
-				MSGRemoveHandle(diStr->hCard, dwContextIndex);
-		break;
-
-	case SCARD_BEGIN_TRANSACTION:
-		beStr = ((begin_struct *) msgStruct->data);
-		rv = MSGCheckHandleAssociation(beStr->hCard, dwContextIndex);
-		if (rv != 0) return rv;
-		beStr->rv = SCardBeginTransaction(beStr->hCard);
-		break;
-
-	case SCARD_END_TRANSACTION:
-		enStr = ((end_struct *) msgStruct->data);
-		rv = MSGCheckHandleAssociation(enStr->hCard, dwContextIndex);
-		if (rv != 0) return rv;
-		enStr->rv =
-			SCardEndTransaction(enStr->hCard, enStr->dwDisposition);
-		break;
-
-	case SCARD_CANCEL_TRANSACTION:
-		caStr = ((cancel_struct *) msgStruct->data);
-		rv = MSGCheckHandleAssociation(caStr->hCard, dwContextIndex);
-		if (rv != 0) return rv;
-		caStr->rv = SCardCancelTransaction(caStr->hCard);
-		break;
-
-	case SCARD_STATUS:
-		stStr = ((status_struct *) msgStruct->data);
-		rv = MSGCheckHandleAssociation(stStr->hCard, dwContextIndex);
-		if (rv != 0) return rv;
-
-		cchReaderLen = stStr->pcchReaderLen;
-		dwState = stStr->dwState;
-		dwProtocol = stStr->dwProtocol;
-		cbAtrLen = stStr->pcbAtrLen;
-
-		/* avoids buffer overflow */
-		if ((cchReaderLen > sizeof(stStr->mszReaderNames))
-			|| (cbAtrLen > sizeof(stStr->pbAtr)))
-		{
-			stStr->rv = SCARD_E_INSUFFICIENT_BUFFER ;
-			break;
-		}
-
-		stStr->rv = SCardStatus(stStr->hCard, stStr->mszReaderNames,
-			&cchReaderLen, &dwState,
-			&dwProtocol, stStr->pbAtr, &cbAtrLen);
-
-		stStr->pcchReaderLen = cchReaderLen;
-		stStr->dwState = dwState;
-		stStr->dwProtocol = dwProtocol;
-		stStr->pcbAtrLen = cbAtrLen;
-		break;
-
-	case SCARD_TRANSMIT:
-		trStr = ((transmit_struct *) msgStruct->data);
-		rv = MSGCheckHandleAssociation(trStr->hCard, dwContextIndex);
-		if (rv != 0) return rv;
-
-		/* avoids buffer overflow */
-		if ((trStr->pcbRecvLength > sizeof(trStr->pbRecvBuffer))
-			|| (trStr->cbSendLength > sizeof(trStr->pbSendBuffer)))
-		{
-			trStr->rv = SCARD_E_INSUFFICIENT_BUFFER ;
-			break;
-		}
-
-		ioSendPci.dwProtocol = trStr->ioSendPciProtocol;
-		ioSendPci.cbPciLength = trStr->ioSendPciLength;
-		ioRecvPci.dwProtocol = trStr->ioRecvPciProtocol;
-		ioRecvPci.cbPciLength = trStr->ioRecvPciLength;
-		cbRecvLength = trStr->pcbRecvLength;
-
-		trStr->rv = SCardTransmit(trStr->hCard, &ioSendPci,
-			trStr->pbSendBuffer, trStr->cbSendLength,
-			&ioRecvPci, trStr->pbRecvBuffer,
-			&cbRecvLength);
-
-		trStr->ioSendPciProtocol = ioSendPci.dwProtocol;
-		trStr->ioSendPciLength = ioSendPci.cbPciLength;
-		trStr->ioRecvPciProtocol = ioRecvPci.dwProtocol;
-		trStr->ioRecvPciLength = ioRecvPci.cbPciLength;
-		trStr->pcbRecvLength = cbRecvLength;
-
-		break;
-
-	case SCARD_CONTROL:
-		ctStr = ((control_struct *) msgStruct->data);
-		rv = MSGCheckHandleAssociation(ctStr->hCard, dwContextIndex);
-		if (rv != 0) return rv;
-
-		/* avoids buffer overflow */
-		if ((ctStr->cbRecvLength > sizeof(ctStr->pbRecvBuffer))
-			|| (ctStr->cbSendLength > sizeof(ctStr->pbSendBuffer)))
-		{
-			ctStr->rv = SCARD_E_INSUFFICIENT_BUFFER;
-			break;
-		}
-
-		dwBytesReturned = ctStr->dwBytesReturned;
-
-		ctStr->rv = SCardControl(ctStr->hCard, ctStr->dwControlCode,
-			ctStr->pbSendBuffer, ctStr->cbSendLength,
-			ctStr->pbRecvBuffer, ctStr->cbRecvLength,
-			&dwBytesReturned);
-
-		ctStr->dwBytesReturned = dwBytesReturned;
-
-		break;
-
-	case SCARD_GET_ATTRIB:
-		gsStr = ((getset_struct *) msgStruct->data);
-		rv = MSGCheckHandleAssociation(gsStr->hCard, dwContextIndex);
-		if (rv != 0) return rv;
-
-		/* avoids buffer overflow */
-		if (gsStr->cbAttrLen > sizeof(gsStr->pbAttr))
-		{
-			gsStr->rv = SCARD_E_INSUFFICIENT_BUFFER ;
-			break;
-		}
-
-		cbAttrLen = gsStr->cbAttrLen;
-
-		gsStr->rv = SCardGetAttrib(gsStr->hCard, gsStr->dwAttrId,
-			gsStr->pbAttr, &cbAttrLen);
-
-		gsStr->cbAttrLen = cbAttrLen;
-
-		break;
-
-	case SCARD_SET_ATTRIB:
-		gsStr = ((getset_struct *) msgStruct->data);
-		rv = MSGCheckHandleAssociation(gsStr->hCard, dwContextIndex);
-		if (rv != 0) return rv;
-
-		/* avoids buffer overflow */
-		if (gsStr->cbAttrLen <= sizeof(gsStr->pbAttr))
-		{
-			gsStr->rv = SCARD_E_INSUFFICIENT_BUFFER ;
-			break;
-		}
-
-		gsStr->rv = SCardSetAttrib(gsStr->hCard, gsStr->dwAttrId,
-			gsStr->pbAttr, gsStr->cbAttrLen);
-		break;
-
-	case SCARD_TRANSMIT_EXTENDED:
-		{
-			transmit_struct_extended *treStr;
-			unsigned char pbSendBuffer[MAX_BUFFER_SIZE_EXTENDED];
-			unsigned char pbRecvBuffer[MAX_BUFFER_SIZE_EXTENDED];
-
-			treStr = ((transmit_struct_extended *) msgStruct->data);
-			rv = MSGCheckHandleAssociation(treStr->hCard, dwContextIndex);
-			if (rv != 0) return rv;
-
-			/* avoids buffer overflow */
-			if ((treStr->size > sizeof(pbSendBuffer))
-				|| (treStr->cbSendLength > sizeof(pbSendBuffer))
-				|| (treStr->pcbRecvLength > sizeof(pbRecvBuffer)))
-			{
-				treStr->rv = SCARD_E_INSUFFICIENT_BUFFER;
-				break;
-			}
-
-			/* on more block to read? */
-			if (treStr->size > PCSCLITE_MAX_MESSAGE_SIZE)
-			{
-				/* copy the first APDU part */
-				memcpy(pbSendBuffer, treStr->data,
-					PCSCLITE_MAX_MESSAGE_SIZE-offsetof(transmit_struct_extended, data));
-
-				/* receive the second block */
-				rv = SHMMessageReceive(
-					pbSendBuffer+PCSCLITE_MAX_MESSAGE_SIZE-offsetof(transmit_struct_extended, data),
-					treStr->size - PCSCLITE_MAX_MESSAGE_SIZE,
-					psContext[dwContextIndex].dwClientID,
-					PCSCLITE_SERVER_ATTEMPTS);
-				if (rv)
-					Log1(PCSC_LOG_CRITICAL, "reception failed");
-			}
-			else
-				memcpy(pbSendBuffer, treStr->data, treStr->cbSendLength);
-
-			ioSendPci.dwProtocol = treStr->ioSendPciProtocol;
-			ioSendPci.cbPciLength = treStr->ioSendPciLength;
-			ioRecvPci.dwProtocol = treStr->ioRecvPciProtocol;
-			ioRecvPci.cbPciLength = treStr->ioRecvPciLength;
-			cbRecvLength = treStr->pcbRecvLength;
-
-			treStr->rv = SCardTransmit(treStr->hCard, &ioSendPci,
-				pbSendBuffer, treStr->cbSendLength,
-				&ioRecvPci, pbRecvBuffer,
-				&cbRecvLength);
-
-			treStr->ioSendPciProtocol = ioSendPci.dwProtocol;
-			treStr->ioSendPciLength = ioSendPci.cbPciLength;
-			treStr->ioRecvPciProtocol = ioRecvPci.dwProtocol;
-			treStr->ioRecvPciLength = ioRecvPci.cbPciLength;
-			treStr->pcbRecvLength = cbRecvLength;
-
-			treStr->size = offsetof(transmit_struct_extended, data) + treStr->pcbRecvLength;
-			if (treStr->size > PCSCLITE_MAX_MESSAGE_SIZE)
-			{
-				/* two blocks */
-				memcpy(treStr->data, pbRecvBuffer, PCSCLITE_MAX_MESSAGE_SIZE
-					- offsetof(transmit_struct_extended, data));
-
-				rv = SHMMessageSend(msgStruct, sizeof(*msgStruct),
-					psContext[dwContextIndex].dwClientID,
-					PCSCLITE_SERVER_ATTEMPTS);
-				if (rv)
-					Log1(PCSC_LOG_CRITICAL, "transmission failed");
-
-				rv = SHMMessageSend(pbRecvBuffer + PCSCLITE_MAX_MESSAGE_SIZE
-					- offsetof(transmit_struct_extended, data),
-					treStr->size - PCSCLITE_MAX_MESSAGE_SIZE,
-					psContext[dwContextIndex].dwClientID,
-					PCSCLITE_SERVER_ATTEMPTS);
-				if (rv)
-					Log1(PCSC_LOG_CRITICAL, "transmission failed");
-			}
-			else
-			{
-				/* one block only */
-				memcpy(treStr->data, pbRecvBuffer, treStr->pcbRecvLength);
-
-				rv = SHMMessageSend(msgStruct, sizeof(*msgStruct),
-					psContext[dwContextIndex].dwClientID,
-					PCSCLITE_SERVER_ATTEMPTS);
-				if (rv)
-					Log1(PCSC_LOG_CRITICAL, "transmission failed");
-			}
-		}
-		break;
-
-	case SCARD_CONTROL_EXTENDED:
-		{
-			control_struct_extended *cteStr;
-			unsigned char pbSendBuffer[MAX_BUFFER_SIZE_EXTENDED];
-			unsigned char pbRecvBuffer[MAX_BUFFER_SIZE_EXTENDED];
-
-			cteStr = ((control_struct_extended *) msgStruct->data);
-			rv = MSGCheckHandleAssociation(cteStr->hCard, dwContextIndex);
-			if (rv != 0) return rv;
-
-			/* avoids buffer overflow */
-			if ((cteStr->size > sizeof(pbSendBuffer))
-				|| (cteStr->cbSendLength > sizeof(pbSendBuffer))
-				|| (cteStr->cbRecvLength > sizeof(pbRecvBuffer)))
-			{
-				cteStr->rv = SCARD_E_INSUFFICIENT_BUFFER;
-				break;
-			}
-
-			/* on more block to read? */
-			if (cteStr->size > PCSCLITE_MAX_MESSAGE_SIZE)
-			{
-				/* copy the first data part */
-				memcpy(pbSendBuffer, cteStr->data,
-					PCSCLITE_MAX_MESSAGE_SIZE-sizeof(*cteStr));
-
-				/* receive the second block */
-				rv = SHMMessageReceive(
-					pbSendBuffer+PCSCLITE_MAX_MESSAGE_SIZE-sizeof(*cteStr),
-					cteStr->size - PCSCLITE_MAX_MESSAGE_SIZE,
-					psContext[dwContextIndex].dwClientID,
-					PCSCLITE_SERVER_ATTEMPTS);
-				if (rv)
-					Log1(PCSC_LOG_CRITICAL, "reception failed");
-			}
-			else
-				memcpy(pbSendBuffer, cteStr->data, cteStr->cbSendLength);
-
-			dwBytesReturned = cteStr->dwBytesReturned;
-
-			cteStr->rv = SCardControl(cteStr->hCard, cteStr->dwControlCode,
-				pbSendBuffer, cteStr->cbSendLength,
-				pbRecvBuffer, cteStr->cbRecvLength,
-				&dwBytesReturned);
-
-			cteStr->dwBytesReturned = dwBytesReturned;
-
-			cteStr->size = sizeof(*cteStr) + cteStr->dwBytesReturned;
-			if (cteStr->size > PCSCLITE_MAX_MESSAGE_SIZE)
-			{
-				/* two blocks */
-				memcpy(cteStr->data, pbRecvBuffer, PCSCLITE_MAX_MESSAGE_SIZE
-					- sizeof(*cteStr));
-
-				rv = SHMMessageSend(msgStruct, sizeof(*msgStruct),
-					psContext[dwContextIndex].dwClientID,
-					PCSCLITE_SERVER_ATTEMPTS);
-				if (rv)
-					Log1(PCSC_LOG_CRITICAL, "transmission failed");
-
-				rv = SHMMessageSend(pbRecvBuffer + PCSCLITE_MAX_MESSAGE_SIZE
-					- sizeof(*cteStr),
-					cteStr->size - PCSCLITE_MAX_MESSAGE_SIZE,
-					psContext[dwContextIndex].dwClientID,
-					PCSCLITE_SERVER_ATTEMPTS);
-				if (rv)
-					Log1(PCSC_LOG_CRITICAL, "transmission failed");
-			}
-			else
-			{
-				/* one block only */
-				memcpy(cteStr->data, pbRecvBuffer, cteStr->dwBytesReturned);
-
-				rv = SHMMessageSend(msgStruct, sizeof(*msgStruct),
-					psContext[dwContextIndex].dwClientID,
-					PCSCLITE_SERVER_ATTEMPTS);
-				if (rv)
-					Log1(PCSC_LOG_CRITICAL, "transmission failed");
-			}
-		}
-		break;
-
-	default:
-		Log2(PCSC_LOG_CRITICAL, "Unknown command: %d", msgStruct->command);
-		return -1;
-	}
-
-	return 0;
+
+buffer_overflow:
+	Log2(PCSC_LOG_DEBUG, "Buffer overflow detected: %d", filedes);
+	goto exit;
+wrong_length:
+	Log2(PCSC_LOG_DEBUG, "Wrong length: %d", filedes);
+exit:
+	(void)SYS_CloseFile(filedes);
+	(void)MSGCleanupClient(dwContextIndex);
+	(void)SYS_ThreadExit((LPVOID) NULL);
 }
 
 LONG MSGSignalClient(uint32_t filedes, LONG rv)




More information about the Pcsclite-cvs-commit mailing list