PCSC那事儿(十一--SCardEstablishContext)
来源:互联网 发布:淘宝客服介入后撤销 编辑:程序博客网 时间:2024/05/18 06:28
这个很典型的,socket写操作。采用非阻塞方式写数据。
同样的SHMMessageReceive也很典型,socket读操作。采用非阻塞方式读数据。不再罗列了。
提前说明,testpcsc和pcscd之间的通讯,是通过结构体sharedSegmentMsg (仅仅是通用的一个,后续的
用到的API会详细解说),无论收还是发,都是通过这个结构体解包数据和打包数据。
364 sharedSegmentMsg msgStruct;
在winscard_msg.h中定义:
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;
unsigned char key[PCSCLITE_MSG_KEY_LEN]; /* 16 bytes */
union
{
unsigned char data[PCSCLITE_MAX_MESSAGE_SIZE];
struct version_struct veStr;
};
}
sharedSegmentMsg, *psharedSegmentMsg;
到这里,testpcsc第一次运行的上下文建立的特别处理结束了。第一次,容易吗?
不容易。设置isExecuted = 1.
511~545行,
建立establish_struct结构,进行通讯。
363 establish_struct scEstablishStruct;
并向pcscd发送请求,请求在pcscd内部建立对应的上下文(服务器应用程序上下文)。
519行,WrapSHMWrite
是 SHMMessageSend的一个包装。
定义在winscard_msg.c中
实现如下:
412 INTERNAL int32_t WrapSHMWrite(uint32_t command, uint32_t dwClientID,
413 uint64_t size, uint32_t blockAmount, void *data_void)
414 {
415 char *data = data_void;
416
417 sharedSegmentMsg msgStruct;
418 int ret;
419
420 /*
421 * Set the appropriate packet parameters
422 */
423
424 memset(&msgStruct, 0, sizeof(msgStruct));
425 msgStruct.mtype = CMD_FUNCTION;
426 msgStruct.user_id = SYS_GetUID();
427 msgStruct.group_id = SYS_GetGID();
428 msgStruct.command = command;
429 msgStruct.date = time(NULL);
430 memset(msgStruct.key, 0, sizeof(msgStruct.key));
431 if ((SCARD_TRANSMIT_EXTENDED == command)
432 || (SCARD_CONTROL_EXTENDED == command))
433 {
434 /* first block */
435 if (size > sizeof(msgStruct.data))
436 memcpy(msgStruct.data, data, sizeof(msgStruct.data));
437 else
438 {
439 memcpy(msgStruct.data, data, size);
440 memset(msgStruct.data+size, 0, sizeof(msgStruct.data)-size);
441 }
442
443 ret = SHMMessageSend(&msgStruct, sizeof(msgStruct), dwClientID,
444 blockAmount);
445
446 /* do not send an empty second block */
447 if ((0 == ret) && (size > sizeof(msgStruct.data)))
448 {
449 /* second block */
450 ret = SHMMessageSend(data+sizeof(msgStruct.data),
451 size-sizeof(msgStruct.data), dwClientID, blockAmount);
452 }
453 }
454 else
455 {
456 memcpy(msgStruct.data, data, size);
457
458 ret = SHMMessageSend(&msgStruct, sizeof(msgStruct), dwClientID,
459 blockAmount);
460 }
461
462 if (SCARD_TRANSMIT == command)
463 /* clean APDU buffer to remove any possible PIN or secret value */
464 memset(msgStruct.data, 0, min(size, sizeof(msgStruct.data)));
465
466 return ret;
467 }
实际上分了两次发送,第一次发送了size大小数据的前PCSCLITE_MAX_MESSAGE_SIZE字节,余下的作为一次性发送.
而这里的接收采用SHMClientRead 仅仅是SHMMessageReceive的简单包装。
SHMClientRead定义在winscard_msg.c
实现如下:
57 INTERNAL int32_t SHMClientRead(psharedSegmentMsg msgStruct, uint32_t dwClien tID, int32_t blockamount)
58 {
59 return SHMMessageReceive(msgStruct, sizeof(*msgStruct), dwClientID, blockamount);
60 }
远远没有WrapSHMWrite麻烦(麻烦不代表复杂)。
SHMMessageReceive,就是非阻塞读取,提过了。
540 行,SCardGetContextIndiceTH(scEstablishStruct.hContext)
定义在winscard_clnt.c,实现如下:
3640 static LONG SCardGetContextIndiceTH(SCARDCONTEXT hContext)
3641 {
3642 int i;
3643
3644 /*
3645 * Find this context and return its spot in the array
3646 */
3647 for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
3648 {
3649 if ((hContext == psContextMap[i].hContext) && (hContext != 0))
3650 return i;
3651 }
3652
3653 return -1;
3654 }
540~543行,检查testpcsc内的上下文的hContext是否与接收回来的申请到的
hContext重复。如果重复,则重新发出请求。重复的原因是pcscd产生
hContext的方式。实际上,hContext来自于服务端发出的一个long数据(和随机数有关,所以存在重复)。
而服务端不做重复的检测,产生数据后,直接发回给客户端。
具体见后文(服务端)分析。
545 *phContext = scEstablishStruct.hContext;
看到吗?上面忙的那么多,仅仅为了这一行,终于获取到了上下文和dwClientID。
这就是客户端想要“的结果的结果”。
550 rv = SCardAddContext(*phContext, dwClientID);
这行又做了什么?
3585 static LONG SCardAddContext(SCARDCONTEXT hContext, DWORD dwClientID)
3586 {
3587 int i;
3588
3589 for (i = 0; i < PCSCLITE_MAX_APPLICATION_CONTEXTS; i++)
3590 {
3591 if (psContextMap[i].hContext == 0)
3592 {
3593 psContextMap[i].hContext = hContext;
3594 psContextMap[i].dwClientID = dwClientID;
3595 psContextMap[i].contextBlockStatus = BLOCK_STATUS_RESUME;
3596 psContextMap[i].mMutex = malloc(sizeof(PCSCLITE_MUTEX));
3597 (void)SYS_MutexInit(psContextMap[i].mMutex);
3598 return SCARD_S_SUCCESS;
3599 }
3600 }
3601
3602 return SCARD_E_NO_MEMORY;
3603 }
这个是?... 那还用说吗?上面取得了hContext,dwClientID,当然要提交给上下文,
psContextMap,进行上下文注册,并初始化其它的结构。
很象官场,不是吗?要注册,要管理。
客户端的SCardEstablishContext分析完成。
很容易理解吧。那么继续前进。
问:到哪里了?
答案是,别晕了。回去了。
回到testpcsc.c的101行了。
101 rv = SCardIsValidContext(hContext);
- PCSC那事儿(十一--SCardEstablishContext)
- PCSC那事儿(八--SCardEstablishContext)
- PCSC那事儿(九--SCardEstablishContext)
- PCSC那事儿(十--SCardEstablishContext)
- PCSC那事儿(二十一--SCardControl)
- PCSC那事儿(一)
- PCSC那事儿(二)
- PCSC那事儿(三)
- PCSC那事儿(四)
- PCSC那事儿(五)
- PCSC那事儿(六)
- PCSC那事儿(七)
- PCSC那事儿(十二--SCardIsValidContext)
- PCSC那事儿(十三--SCardListReaderGroups)
- PCSC那事儿(十四--SCardReleaseContext)
- PCSC那事儿(十五--SCardFreeMemory)
- PCSC那事儿(十六--SCardListReaders)
- PCSC那事儿(十七--SCardGetStatusChange)
- 运用C#创建一个.Net下的Web Service
- S2Dao
- Memory Leak Check
- 传奇私服爱好者进
- 硬盘接口类型
- PCSC那事儿(十一--SCardEstablishContext)
- 下载GECKO,开始编程之旅
- 07 Spring JDBC Support Spring对于JDBC的支持
- C# 查找打开的窗口
- BitBlt函数的用法
- How to get information of .a/.so
- c++ builder选择文件夹
- GWY后感
- 把ERP家庭化 - 理解ERP