前言:本实例中以APDU协议为例进行封包和发包(这里的发包以一个报文为单位,在实际工作中应该是以实际带宽决定吧)。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//SYS
#define MTU_DATA 16
#define MTU (MTU_DATA + 6)
//USER
#define RAW_LEN 100
//APDU Format
#define CLA 0
#define INS 1
#define P1 2
#define P2 3
#define Lc 4
#define Le(data_len) (5 + (data_len))
//example:apdu
//CLA INS P1 P2 | Lc data Le
int
warp_packet(char *rawdata, int raw_len, char **newdata, int *new_len, int *count)
{
int loop, apdu_count, data_len;
*new_len = 0;
*count = 0;
loop = raw_len;
apdu_count = (raw_len/MTU_DATA) + (((raw_len%MTU_DATA) > 0) ? 1:0);
*count = (apdu_count > 0)?apdu_count:1;
*newdata = malloc( sizeof(char) * MTU * (*count) );
if(*newdata == NULL){
printf("malloc is failed\n");
return -1;
}
memset(*newdata, 0, sizeof(char) * MTU * (*count));
for(int i = 0; i < *count; ++i){
//head fill
(*newdata)[CLA + MTU*i] = 0x00;
(*newdata)[INS + MTU*i] = 0x01;
(*newdata)[P1 + MTU*i] = 0x02;
(*newdata)[P2 + MTU*i] = 0x03;
//body fill
data_len = (loop > MTU_DATA)?MTU_DATA:(loop%MTU_DATA);
(*newdata)[Lc + MTU*i] = data_len;
memcpy(*newdata + Lc + MTU*i + 1, rawdata + i*MTU_DATA, data_len);
(*newdata)[Le(data_len) + i*MTU] = data_len;
loop -= MTU_DATA;
*new_len += 6 + data_len;
}
return 0;
}
void
send(char *buff, int len)
{
printf("send:");
for(int i = 0; i < len; ++i)
printf("%x ", buff[i]);
printf("\n");
}
void
multi_send(char *data, int len, int count)
{
for(int i = 0; i < count; ++i){
if(i == (count-1))
send(data + MTU*i, len%MTU);
else
send(data + MTU*i, MTU);
}
}
void
gen_data(char *array, int n)
{
for(int i = 0; i < n; ++i)
array[i] = i;
}
int
main(int argc, char const *argv[])
{
char rawdata[RAW_LEN];
char *newdata;
int new_len, count;
gen_data(rawdata, RAW_LEN);
for(int i = 0; i < RAW_LEN; ++i){
printf("%x ", rawdata[i]);
}
printf("\n");
warp_packet(rawdata, RAW_LEN, &newdata, &new_len, &count);
printf("count:%d new_len:%d \n", count, new_len);
for(int i = 0; i < new_len; ++i){
printf("%x ", newdata[i]);
if((i+1)%MTU == 0)
printf("\n");
}
printf("\n");
multi_send(newdata, new_len, count);
return 0;
}