PCSC那事儿(十一--SCardEstablishContext)

来源:互联网 发布:淘宝客服介入后撤销 编辑:程序博客网 时间:2024/05/18 06:28

 

这个很典型的,socket写操作。采用非阻塞方式写数据。

同样的SHMMessageReceive也很典型,socket读操作。采用非阻塞方式读数据。不再罗列了。

 

提前说明,testpcscpcscd之间的通讯,是通过结构体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.c101行了。

101         rv = SCardIsValidContext(hContext);

 

 

 

原创粉丝点击