PCSC那事儿(十一--SCardEstablishContext)

 

这个很典型的, 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);

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值