用户自定义结构数据与VARIANT转换 .

简介: 用户自定义结构数据与VARIANT转换 cheungmine 将用户自定义的C结构数据存储成VARIANT类型,需要时再将VARIANT类型转为用户自定义的结构数据,有十分现实的意义,既然我们不想为这样的结构数据写一个COM包装类。

用户自定义结构数据与VARIANT转换

cheungmine

将用户自定义的C结构数据存储成VARIANT类型,需要时再将VARIANT类型转为用户自定义的结构数据,有十分现实的意义,既然我们不想为这样的结构数据写一个COM包装类。虽然有很多方法和手段生成这样的VARIANT,但是,多数时候可能需要一个更加简单的,灵活的方法。我在做远程过程调用的C接口时,忽然联想到,既然RPC可以把任何数据以字节的形式发送,那么,就可以利用这个机制,把结构打包成字节数组。而字节数据是可以很方便地存储在VARIANT中。

 

这个过程是广为人知的,但是,真正把结构列集成字节数组,如果不想使用某些标称的序列化的方法,而全部自己写,的确要费一番功夫。不是

技术有多难,是很繁琐。我把前2年写的代码翻出来,简单调用一下,就有了这篇文章。采用我的方法,C/C++程序员可以把自己定义的结构放到VARIANT、CComVariant、COleVariant等各种VARIANT中,也可以反向转换。而VARIANT是可以很方便地在COM接口中传递。这样,就多了一种在自动化COM接口中传递自定义结构的手段。

 

不多说废话,全部内容见下面的代码,我还会上传整个工程。

struct2variant.cpp 如下:

 

  1. ///////////////////////////////////////////////////////////////////////   
  2. // struct2variant.cpp   
  3. // cheungmine@gmail.com   
  4. // 2010-6   
  5. // 下面的程序演示了如何在用户自定义的结构和VARIANT类型之间转换   
  6. // 保留所有权利   
  7. //   
  8. #include "stdafx.h"   
  9. #include "rpc/rpcapi.h"   
  10. #include <assert.h>   
  11. #ifdef _DEBUG   
  12. #  pragma comment(lib, "rpc/rpclib/debug/rpclib.lib")   
  13. #else   
  14. #  pragma comment(lib, "rpc/rpclib/release/rpclib.lib")   
  15. #endif   
  16. // 自定义结构标识   
  17. #define MY_STRUCT_ID  101   // 标识结构的任意数字   
  18. typedef struct _PointF  
  19. {  
  20.     double x;  
  21.     double y;  
  22. }PointF;  
  23. // 自定义结构   
  24. typedef struct _MyStruct  
  25. {  
  26.     CHAR      id[32];  
  27.     CHAR      server[130];  
  28.     CHAR      instance[10];  
  29.     CHAR      userid[32];  
  30.     BOOL      isdraw;  
  31.     ULONG     token;  
  32.     LONG      timeout;  
  33.     LONG      keepalive;  
  34.     LONG      reserved;  
  35.     BOOL      status;  
  36.     LONG      capacity;  
  37.     LONG volatile counter;  
  38.     // 说明如何保存变长数组   
  39.     SHORT     numPts;  
  40.     PointF   *ptArray;    
  41. }MyStruct;  
  42. void PrintfMyStruct(const char *desc, MyStruct *data)  
  43. {  
  44.     printf("==========%s==========/n", desc);  
  45.     printf("id=%s/n", data->id);  
  46.     printf("server=%s/n", data->server);  
  47.     printf("instance=%s/n", data->instance);  
  48.     printf("userid=%s/n", data->userid);  
  49.     printf("isdraw=%d/n", data->isdraw);  
  50.     printf("token=%d/n", data->token);  
  51.     printf("timeout=%d/n", data->timeout);  
  52.     printf("keepalive=%d/n", data->keepalive);  
  53.     printf("reserved=%d/n", data->reserved);  
  54.     printf("status=%d/n", data->status);  
  55.     printf("capacity=%d/n", data->capacity);  
  56.     printf("counter=%d/n", data->counter);  
  57.     printf("numPts=%d/n", data->numPts);  
  58.     for(int i=0; i<data->numPts; i++)  
  59.         printf("ptArray[%d]= (x=%.3lf,     y=%.3lf)/n", i, data->ptArray[i].x, data->ptArray[i].y);  
  60. }  
  61. static HRESULT CreateStreamFromBytes(BYTE *inBytes, DWORD cbSize, IStream **ppStm)  
  62. {  
  63.     HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, 0);  
  64.     ATLASSERT(hGlobal);  
  65.     if (!hGlobal)  
  66.         return E_OUTOFMEMORY;  
  67.       
  68.     CComPtr<IStream> spStm;  
  69.     HRESULT hr = CreateStreamOnHGlobal(hGlobal, TRUE, &spStm);  
  70.     ATLASSERT(hr == S_OK);  
  71.     if (hr != S_OK || spStm == 0){  
  72.         GlobalFree(hGlobal);  
  73.         return hr;  
  74.     }  
  75.       
  76.     ULONG  ulWritten = 0;  
  77.     hr = spStm->Write(inBytes, cbSize, &ulWritten);  
  78.     if (hr != S_OK || ulWritten != cbSize)  
  79.         return E_FAIL;  
  80.     return spStm.CopyTo(ppStm);  
  81. }  
  82. ////////////////////////////////////////////////////////////////////   
  83. // 列集自定义数据到VARIANT   
  84. //   
  85. static void MarshallMyStruct(MyStruct *inData, VARIANT *outVar)  
  86. {  
  87.     assert(inData && outVar);  
  88.     rpc_invoke_descriptor  inv  = {0};  
  89.     rpc_invoke_init(&inv, MY_STRUCT_ID, 14);    // 14个参数   
  90.     // 下面每个结构成员参数都需要按次序绑定   
  91.     rpc_invoke_bind_param(&inv,   
  92.                 0,                    /* 结构成员参数索引0-based */  
  93.                 RPCT_STRING,          /* 指明字符串数组类型 */  
  94.                 (void*)inData->id,     /* 指向实际数据的指针 */  
  95.                 strlen(inData->id)+1, /* 只需要保存有效的数据 */  
  96.                 0                     /*0 表示我们不具有id的所有权(不负责释放内存) */  
  97.             );  
  98.     rpc_invoke_bind_param(&inv,   
  99.                 1,  
  100.                 RPCT_STRING,  
  101.                 (void*)inData->server,  
  102.                 strlen(inData->server)+1,  
  103.                 0  
  104.             );  
  105.     rpc_invoke_bind_param(&inv,   
  106.                 2,  
  107.                 RPCT_STRING,  
  108.                 (void*)inData->instance,  
  109.                 strlen(inData->instance)+1,  
  110.                 0  
  111.             );  
  112.     rpc_invoke_bind_param(&inv,   
  113.                 3,  
  114.                 RPCT_STRING,  
  115.                 (void*)inData->userid,  
  116.                 strlen(inData->userid)+1,  
  117.                 0  
  118.             );  
  119.     rpc_invoke_bind_param(&inv,   
  120.                 4,  
  121.                 RPCT_BOOL,  
  122.                 (void*) &inData->isdraw,  
  123.                 0,  /* 不是数组, 为0 */  
  124.                 0  
  125.             );  
  126.     rpc_invoke_bind_param(&inv,   
  127.                 5,  
  128.                 RPCT_ULONG,  
  129.                 (void*) &inData->token,  
  130.                 0,  
  131.                 0  
  132.             );  
  133.     rpc_invoke_bind_param(&inv,   
  134.                 6,  
  135.                 RPCT_LONG,  
  136.                 (void*) &inData->timeout,  
  137.                 0,  
  138.                 0  
  139.             );  
  140.     rpc_invoke_bind_param(&inv,   
  141.                 7,  
  142.                 RPCT_LONG,  
  143.                 (void*) &inData->keepalive,  
  144.                 0,  
  145.                 0  
  146.             );  
  147.     rpc_invoke_bind_param(&inv,   
  148.                 8,  
  149.                 RPCT_LONG,  
  150.                 (void*) &inData->reserved,  
  151.                 0,  
  152.                 0  
  153.             );  
  154.     rpc_invoke_bind_param(&inv,   
  155.                 9,  
  156.                 RPCT_BOOL,  
  157.                 (void*) &inData->status,  
  158.                 0,  
  159.                 0  
  160.             );  
  161.     rpc_invoke_bind_param(&inv,   
  162.                 10,  
  163.                 RPCT_LONG,  
  164.                 (void*) &inData->capacity,  
  165.                 0,  
  166.                 0  
  167.             );  
  168.     rpc_invoke_bind_param(&inv,   
  169.                 11,  
  170.                 RPCT_LONG,  
  171.                 (void*) &inData->counter,  
  172.                 0,  
  173.                 0  
  174.             );  
  175.     rpc_invoke_bind_param(&inv,   
  176.                 12,  
  177.                 RPCT_SHORT,  
  178.                 (void*) &inData->numPts,  
  179.                 0,  
  180.                 0  
  181.             );  
  182.     rpc_invoke_bind_param(&inv,   
  183.                 13,  
  184.                 RPCT_DOUBLE,    /* 简单结构的成员类型 */  
  185.                 (void*) inData->ptArray, /* 内存结构=[x1,y1,x2,y2,...,xn,yn], 千万不可写成:(void*) &inData->ptArray */  
  186.                 inData->numPts * (sizeof(PointF)/sizeof(double)), /* double类型成员的数目=点数x2 */  
  187.                 0  
  188.             );  
  189.     /* 计算调用消息的字节总数 */  
  190.     dword_t cbOut = rpc_invoke_get_size(&inv);  
  191.     char *outBuf = (char*) malloc(cbOut);  
  192.       
  193.     /* 列集全部数据到totalBuf中 */  
  194.     rpc_invoke_marshal(&inv, outBuf, cbOut);  
  195.     //////////////////////////////////////////////////////////   
  196.     // 到此,我们已经在outBuf中保存了结构的全部数据,    
  197.     // 下面把数据转换成IStream进而转换成VARIANT   
  198.     CComPtr<IStream> spStm;  
  199.     CreateStreamFromBytes((BYTE*)outBuf, cbOut, &spStm);  
  200.     VariantInit(outVar);  
  201.     outVar->vt = VT_UNKNOWN;  
  202.     outVar->punkVal = (IUnknown*) spStm.Detach();  
  203.     free(outBuf);  
  204.     rpc_invoke_clear_all(&inv);  
  205. }  
  206. ////////////////////////////////////////////////////////////////////   
  207. // 散集VARIANT到自定义数据   
  208. //   
  209. static void UnmarshallMyStruct(VARIANT *inVar, MyStruct *outData)  
  210. {  
  211.     assert(inVar && outData);  
  212.     assert(inVar->vt==VT_UNKNOWN && inVar->punkVal);  
  213.     HGLOBAL  hGlobal = 0;  
  214.     HRESULT hr = GetHGlobalFromStream((IStream*)inVar->punkVal, &hGlobal);  
  215.     assert(hr==S_OK);  
  216.     size_t  cbData = GlobalSize(hGlobal);  
  217.     char   *pbData = (char*) GlobalLock(hGlobal);  
  218.     char   *rpcHdr = pbData;  
  219.     assert(cbData >= RPC_INVOKE_HEADER_SIZE);  
  220.     assert(rpcHdr[0]=='R' && rpcHdr[1]=='C');  
  221.     rpc_invoke_descriptor  inv={0};  
  222.     rpc_invoke_init(&inv, 0, 0);  
  223.     inv.encPkg = rpcHdr[2];  
  224.     inv.encHdr = rpcHdr[3];  
  225.     assert (inv.encHdr == 0);  
  226.     inv.ordinal = word_ntoh(*((word_t*)(rpcHdr+20)));               // 方法序号: MY_STRUCT_ID   
  227.     assert(inv.ordinal == MY_STRUCT_ID);  
  228.     inv.invToken = dword_ntoh(*((dword_t*)(rpcHdr+4)));             // 用户标识    
  229.     inv.totalBytes = dword_ntoh(*((dword_t*)(rpcHdr+8)));           // 总消息字节数(也许是压缩的)   
  230.     inv.bitsFlag = word_ntoh(*((word_t*)(rpcHdr+12)));              // 标志      
  231.     inv.bigEndian = GET_BIT(inv.bitsFlag, RPC_BIGENDIAN_BIT);       // 客户方列集的字节次序   
  232.     inv.reserved = word_ntoh(*((word_t*)(rpcHdr+14)));              // 保留值   
  233.     inv.result = dword_ntoh(*((dword_t*)(rpcHdr+16)));              // 返回值   
  234.     inv.num_params = word_ntoh(*((word_t*)(rpcHdr+22)));            // 参数数目   
  235.     rpc_invoke_error  err={0};  
  236.     rpc_invoke_unmarshal(&inv, rpcHdr, inv.totalBytes, &inv.params_list, &inv.num_params, &err);  
  237.           
  238.     GlobalUnlock(hGlobal);  
  239.     strncpy_s(outData->id, sizeof(outData->id), (char*) inv.params_list[0].param_bytes, sizeof(outData->id)-1);  
  240.     strncpy_s(outData->server, sizeof(outData->server), (char*) inv.params_list[1].param_bytes, sizeof(outData->server)-1);  
  241.     strncpy_s(outData->instance, sizeof(outData->instance), (char*) inv.params_list[2].param_bytes, sizeof(outData->instance)-1);  
  242.     strncpy_s(outData->userid, sizeof(outData->userid), (char*) inv.params_list[3].param_bytes, sizeof(outData->userid)-1);  
  243.     outData->isdraw = PARAMVALUE(inv.params_list, 4, BOOL);  
  244.     outData->token = PARAMVALUE(inv.params_list, 5, ULONG);  
  245.     outData->timeout = PARAMVALUE(inv.params_list, 6, LONG);  
  246.     outData->keepalive = PARAMVALUE(inv.params_list, 7, LONG);  
  247.     outData->reserved = PARAMVALUE(inv.params_list, 8, LONG);  
  248.     outData->status = PARAMVALUE(inv.params_list, 9, BOOL);  
  249.     outData->capacity = PARAMVALUE(inv.params_list, 10, LONG);  
  250.     outData->counter = PARAMVALUE(inv.params_list, 11, LONG);  
  251.     outData->numPts = PARAMVALUE(inv.params_list, 12, SHORT);  
  252.     // 为输出分配 ptArray   
  253.     outData->ptArray = (PointF*) malloc(sizeof(PointF)*outData->numPts);  
  254.     memcpy(outData->ptArray, inv.params_list[13].param_bytes, sizeof(PointF)*outData->numPts);  
  255.     rpc_invoke_clear_all(&inv);  
  256. }  
  257. int main(int argc, CHAR* argv[])  
  258. {  
  259.     MyStruct     data, data2;  
  260.     CComVariant  var;   // 这个var 可以存储在任何需要使用到的地方   
  261.     // 初始化结构data   
  262.     strcpy_s(data.id, sizeof(data.id), "13890");  
  263.     strcpy_s(data.server, sizeof(data.server), "localhost");  
  264.     strcpy_s(data.instance, sizeof(data.instance), "port:6755");  
  265.     strcpy_s(data.userid, sizeof(data.userid), "cheungmine");  
  266.     data.isdraw = 1;  
  267.     data.token = 54321;  
  268.     data.timeout = 3000;  
  269.     data.keepalive = 6500;  
  270.     data.reserved=0;  
  271.     data.status = 0;  
  272.     data.capacity = 4096;  
  273.     data.counter = 99;  
  274.     data.numPts = 16;  
  275.     data.ptArray = (PointF*) malloc(data.numPts*sizeof(PointF));  
  276.     for(int i=0; i<data.numPts; i++){  
  277.         data.ptArray[i].x = 100+i;  
  278.         data.ptArray[i].y = 200+i;  
  279.     }  
  280.     PrintfMyStruct("input MyStruct", &data);  
  281.       
  282.     // 用户的结构转换为VARIANT: data=>var   
  283.     MarshallMyStruct(&data, &var);  
  284.     free(data.ptArray);  
  285.     // ...使用var   
  286.     // VARIANT转为用户的结构: var=>data   
  287.     UnmarshallMyStruct(&var, &data2);  
  288.     PrintfMyStruct("output MyStruct", &data2);  
  289.     free(data2.ptArray);  
  290. }  
/////////////////////////////////////////////////////////////////////// // struct2variant.cpp // cheungmine@gmail.com // 2010-6 // 下面的程序演示了如何在用户自定义的结构和VARIANT类型之间转换 // 保留所有权利 // #include "stdafx.h" #include "rpc/rpcapi.h" #include <assert.h> #ifdef _DEBUG # pragma comment(lib, "rpc/rpclib/debug/rpclib.lib") #else # pragma comment(lib, "rpc/rpclib/release/rpclib.lib") #endif // 自定义结构标识 #define MY_STRUCT_ID 101 // 标识结构的任意数字 typedef struct _PointF { double x; double y; }PointF; // 自定义结构 typedef struct _MyStruct { CHAR id[32]; CHAR server[130]; CHAR instance[10]; CHAR userid[32]; BOOL isdraw; ULONG token; LONG timeout; LONG keepalive; LONG reserved; BOOL status; LONG capacity; LONG volatile counter; // 说明如何保存变长数组 SHORT numPts; PointF *ptArray; }MyStruct; void PrintfMyStruct(const char *desc, MyStruct *data) { printf("==========%s==========/n", desc); printf("id=%s/n", data->id); printf("server=%s/n", data->server); printf("instance=%s/n", data->instance); printf("userid=%s/n", data->userid); printf("isdraw=%d/n", data->isdraw); printf("token=%d/n", data->token); printf("timeout=%d/n", data->timeout); printf("keepalive=%d/n", data->keepalive); printf("reserved=%d/n", data->reserved); printf("status=%d/n", data->status); printf("capacity=%d/n", data->capacity); printf("counter=%d/n", data->counter); printf("numPts=%d/n", data->numPts); for(int i=0; i<data->numPts; i++) printf("ptArray[%d]= (x=%.3lf, y=%.3lf)/n", i, data->ptArray[i].x, data->ptArray[i].y); } static HRESULT CreateStreamFromBytes(BYTE *inBytes, DWORD cbSize, IStream **ppStm) { HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, 0); ATLASSERT(hGlobal); if (!hGlobal) return E_OUTOFMEMORY; CComPtr<IStream> spStm; HRESULT hr = CreateStreamOnHGlobal(hGlobal, TRUE, &spStm); ATLASSERT(hr == S_OK); if (hr != S_OK || spStm == 0){ GlobalFree(hGlobal); return hr; } ULONG ulWritten = 0; hr = spStm->Write(inBytes, cbSize, &ulWritten); if (hr != S_OK || ulWritten != cbSize) return E_FAIL; return spStm.CopyTo(ppStm); } //////////////////////////////////////////////////////////////////// // 列集自定义数据到VARIANT // static void MarshallMyStruct(MyStruct *inData, VARIANT *outVar) { assert(inData && outVar); rpc_invoke_descriptor inv = {0}; rpc_invoke_init(&inv, MY_STRUCT_ID, 14); // 14个参数 // 下面每个结构成员参数都需要按次序绑定 rpc_invoke_bind_param(&inv, 0, /* 结构成员参数索引0-based */ RPCT_STRING, /* 指明字符串数组类型 */ (void*)inData->id, /* 指向实际数据的指针 */ strlen(inData->id)+1, /* 只需要保存有效的数据 */ 0 /*0 表示我们不具有id的所有权(不负责释放内存) */ ); rpc_invoke_bind_param(&inv, 1, RPCT_STRING, (void*)inData->server, strlen(inData->server)+1, 0 ); rpc_invoke_bind_param(&inv, 2, RPCT_STRING, (void*)inData->instance, strlen(inData->instance)+1, 0 ); rpc_invoke_bind_param(&inv, 3, RPCT_STRING, (void*)inData->userid, strlen(inData->userid)+1, 0 ); rpc_invoke_bind_param(&inv, 4, RPCT_BOOL, (void*) &inData->isdraw, 0, /* 不是数组, 为0 */ 0 ); rpc_invoke_bind_param(&inv, 5, RPCT_ULONG, (void*) &inData->token, 0, 0 ); rpc_invoke_bind_param(&inv, 6, RPCT_LONG, (void*) &inData->timeout, 0, 0 ); rpc_invoke_bind_param(&inv, 7, RPCT_LONG, (void*) &inData->keepalive, 0, 0 ); rpc_invoke_bind_param(&inv, 8, RPCT_LONG, (void*) &inData->reserved, 0, 0 ); rpc_invoke_bind_param(&inv, 9, RPCT_BOOL, (void*) &inData->status, 0, 0 ); rpc_invoke_bind_param(&inv, 10, RPCT_LONG, (void*) &inData->capacity, 0, 0 ); rpc_invoke_bind_param(&inv, 11, RPCT_LONG, (void*) &inData->counter, 0, 0 ); rpc_invoke_bind_param(&inv, 12, RPCT_SHORT, (void*) &inData->numPts, 0, 0 ); rpc_invoke_bind_param(&inv, 13, RPCT_DOUBLE, /* 简单结构的成员类型 */ (void*) inData->ptArray, /* 内存结构=[x1,y1,x2,y2,...,xn,yn], 千万不可写成:(void*) &inData->ptArray */ inData->numPts * (sizeof(PointF)/sizeof(double)), /* double类型成员的数目=点数x2 */ 0 ); /* 计算调用消息的字节总数 */ dword_t cbOut = rpc_invoke_get_size(&inv); char *outBuf = (char*) malloc(cbOut); /* 列集全部数据到totalBuf中 */ rpc_invoke_marshal(&inv, outBuf, cbOut); ////////////////////////////////////////////////////////// // 到此,我们已经在outBuf中保存了结构的全部数据, // 下面把数据转换成IStream进而转换成VARIANT CComPtr<IStream> spStm; CreateStreamFromBytes((BYTE*)outBuf, cbOut, &spStm); VariantInit(outVar); outVar->vt = VT_UNKNOWN; outVar->punkVal = (IUnknown*) spStm.Detach(); free(outBuf); rpc_invoke_clear_all(&inv); } //////////////////////////////////////////////////////////////////// // 散集VARIANT到自定义数据 // static void UnmarshallMyStruct(VARIANT *inVar, MyStruct *outData) { assert(inVar && outData); assert(inVar->vt==VT_UNKNOWN && inVar->punkVal); HGLOBAL hGlobal = 0; HRESULT hr = GetHGlobalFromStream((IStream*)inVar->punkVal, &hGlobal); assert(hr==S_OK); size_t cbData = GlobalSize(hGlobal); char *pbData = (char*) GlobalLock(hGlobal); char *rpcHdr = pbData; assert(cbData >= RPC_INVOKE_HEADER_SIZE); assert(rpcHdr[0]=='R' && rpcHdr[1]=='C'); rpc_invoke_descriptor inv={0}; rpc_invoke_init(&inv, 0, 0); inv.encPkg = rpcHdr[2]; inv.encHdr = rpcHdr[3]; assert (inv.encHdr == 0); inv.ordinal = word_ntoh(*((word_t*)(rpcHdr+20))); // 方法序号: MY_STRUCT_ID assert(inv.ordinal == MY_STRUCT_ID); inv.invToken = dword_ntoh(*((dword_t*)(rpcHdr+4))); // 用户标识 inv.totalBytes = dword_ntoh(*((dword_t*)(rpcHdr+8))); // 总消息字节数(也许是压缩的) inv.bitsFlag = word_ntoh(*((word_t*)(rpcHdr+12))); // 标志 inv.bigEndian = GET_BIT(inv.bitsFlag, RPC_BIGENDIAN_BIT); // 客户方列集的字节次序 inv.reserved = word_ntoh(*((word_t*)(rpcHdr+14))); // 保留值 inv.result = dword_ntoh(*((dword_t*)(rpcHdr+16))); // 返回值 inv.num_params = word_ntoh(*((word_t*)(rpcHdr+22))); // 参数数目 rpc_invoke_error err={0}; rpc_invoke_unmarshal(&inv, rpcHdr, inv.totalBytes, &inv.params_list, &inv.num_params, &err); GlobalUnlock(hGlobal); strncpy_s(outData->id, sizeof(outData->id), (char*) inv.params_list[0].param_bytes, sizeof(outData->id)-1); strncpy_s(outData->server, sizeof(outData->server), (char*) inv.params_list[1].param_bytes, sizeof(outData->server)-1); strncpy_s(outData->instance, sizeof(outData->instance), (char*) inv.params_list[2].param_bytes, sizeof(outData->instance)-1); strncpy_s(outData->userid, sizeof(outData->userid), (char*) inv.params_list[3].param_bytes, sizeof(outData->userid)-1); outData->isdraw = PARAMVALUE(inv.params_list, 4, BOOL); outData->token = PARAMVALUE(inv.params_list, 5, ULONG); outData->timeout = PARAMVALUE(inv.params_list, 6, LONG); outData->keepalive = PARAMVALUE(inv.params_list, 7, LONG); outData->reserved = PARAMVALUE(inv.params_list, 8, LONG); outData->status = PARAMVALUE(inv.params_list, 9, BOOL); outData->capacity = PARAMVALUE(inv.params_list, 10, LONG); outData->counter = PARAMVALUE(inv.params_list, 11, LONG); outData->numPts = PARAMVALUE(inv.params_list, 12, SHORT); // 为输出分配 ptArray outData->ptArray = (PointF*) malloc(sizeof(PointF)*outData->numPts); memcpy(outData->ptArray, inv.params_list[13].param_bytes, sizeof(PointF)*outData->numPts); rpc_invoke_clear_all(&inv); } int main(int argc, CHAR* argv[]) { MyStruct data, data2; CComVariant var; // 这个var 可以存储在任何需要使用到的地方 // 初始化结构data strcpy_s(data.id, sizeof(data.id), "13890"); strcpy_s(data.server, sizeof(data.server), "localhost"); strcpy_s(data.instance, sizeof(data.instance), "port:6755"); strcpy_s(data.userid, sizeof(data.userid), "cheungmine"); data.isdraw = 1; data.token = 54321; data.timeout = 3000; data.keepalive = 6500; data.reserved=0; data.status = 0; data.capacity = 4096; data.counter = 99; data.numPts = 16; data.ptArray = (PointF*) malloc(data.numPts*sizeof(PointF)); for(int i=0; i<data.numPts; i++){ data.ptArray[i].x = 100+i; data.ptArray[i].y = 200+i; } PrintfMyStruct("input MyStruct", &data); // 用户的结构转换为VARIANT: data=>var MarshallMyStruct(&data, &var); free(data.ptArray); // ...使用var // VARIANT转为用户的结构: var=>data UnmarshallMyStruct(&var, &data2); PrintfMyStruct("output MyStruct", &data2); free(data2.ptArray); }

 

 

其中:rpcapi.h可以参考如下:

  1. /** 
  2.  * rpcapi.h -cheungmine@gmail.com 
  3.  * all rights reserved 2009 
  4.  */  
  5. #ifndef _RPCAPI_H__   
  6. #define _RPCAPI_H__   
  7. #include <winsock2.h>   
  8. #pragma comment(lib, "ws2_32.lib")   
  9. #include <process.h>  /* _beginthreadex, _endthread */   
  10. #include "../rc4/unistd.h"   
  11. #include "../rc4/md5.h"   
  12. #include "../rc4/rc4.h"   
  13. #include "rpctype.h"   
  14. #include "rpcerr.h"   
  15. #ifdef __cplusplus   
  16. extern "C" {  
  17. #endif   
  18. static BOOL  _rpc_is_bigendian = (('4321'>>24)=='1');  
  19. #define PARAMVALUE(pl,i,type)     ((type)(*((type*) pl[i].param_bytes)))   
  20. typedef enum  
  21. {  
  22.     RPC_ENCHEADER_BIT  = 0,  
  23.     RPC_ENCPACKAGE_BIT  = 1,  
  24.     RPC_BIGENDIAN_BIT  = 7  
  25. }RPC_BITFLAG_ENUM;  
  26. /** 
  27.  * param descriptor  
  28.  */  
  29. #define RPC_PARAM_HEADER_SIZE  16   
  30. typedef struct _rpc_param_descriptor  
  31. {  
  32.     word_t      param_type;         // 参数类型:变量类型或结构类型   
  33.     word_t      size_type;          // 参数类型尺寸字节   
  34.     size_t      array_size;         // 数组元素数目: 0 不是数组; >0数组   
  35.       
  36.     size_t      param_size;         // 参数数据字节数=参数类型尺寸字节*元素数目   
  37.     void       *param_bytes;        // 指向参数数据的指针的引用, 不复制数据   
  38.     BOOL        is_owner;           // 是否拥有数据. 如果为TRUE, 需要free(param_bytes)   
  39. }rpc_param_descriptor;  
  40. /** 
  41.  * invoke descriptor  
  42.  */  
  43. #define RPC_INVOKE_HEADER_SIZE  24      /* 不可以更改 */   
  44. typedef struct _rpc_invoke_descriptor  
  45. {  
  46.     /* 24字节头 + 内容 
  47.      *  ['RCmn'(4)|用户标识(4)|总消息字节(4)|标志(2)| 保留(2)|原始字节数(4)|方法序号(2)|参数数目(2)] 
  48.      */  
  49.     dword_t                totalBytes;  // 总消息字节4   
  50.     word_t                 bitsFlag;    // 标志位2: [7=BigEndian]   
  51.     word_t                 reserved;    // 保留2   
  52.     dword_t                result;      // 返回值   
  53.     // 内部值, 调用时,需要列集在bitsFlag中   
  54.     dword_t                invToken;  
  55.     byte                   bigEndian;  
  56.     byte                   encHdr;  
  57.     byte                   encPkg;  
  58.     // 如果压缩或加密, 从以下位置内容开始      
  59.     ushort                 ordinal;     // 方法序号2       
  60.     ushort                 num_params;  // 参数数目   
  61.     rpc_param_descriptor  *params_list; // 参数列表   
  62.     // 做为输入时, 存放临时值   
  63.     //   
  64.     char                  *pbBuf;  
  65.     union{  
  66.         char               bVal;  
  67.         long               lVal;  
  68.         short              sVal;  
  69.         float              fVal;  
  70.         double             dVal;  
  71.         __int64            llVal;  
  72.     };  
  73. }rpc_invoke_descriptor;  
  74. /** 
  75.  * connection descriptor 
  76.  */  
  77. typedef struct _rpc_connection_descriptor  
  78. {  
  79.     BOOL               is_bigendian;    // 字节顺序   
  80.     dword_t            token;           // 调用标识   
  81.     dword_t            timeout;         // 超时   
  82.     byte               enc_hdr;         // 头加密标志   
  83.     byte               enc_pkg;         // 参数包加密标志   
  84.     SOCKET             stream;          // SOCKET 连接   
  85.     char               host[130];       // 主机名或IP地址   
  86.     char               port[6];         // 端口号   
  87.       
  88.     rpc_invoke_error   last_err;        // 最近的错误   
  89.     char               buffer[RPC_BUFFSIZE];  // 网络传输缓冲区   
  90. }rpc_connection_descriptor;  
  91. /*============================================================================= 
  92.                               Private Functions 
  93.                  host byte order and network byte order transform 
  94. =============================================================================*/  
  95. static int SafeStringSize(const char* psz)  
  96. {  
  97.     return (int)(psz? (strlen(psz)+1):0);  
  98. }  
  99. /** 
  100.  * More fast than swap_bytes(...) for handle word and dword type 
  101.  */  
  102. #define swap_word_type(x)  ((WORD)(((((WORD)(x))&0x00ff)<<8)|((((WORD)(x))&0xff00)>>8)))   
  103. #define swap_dword_type(x)  ((DWORD)(((((DWORD)(x))&0xff000000)>>24)|((((DWORD)(x))&0x00ff0000)>>8)|((((DWORD)(x))&0x0000ff00)<<8)|((((DWORD)(x))&0x000000ff)<<24)))   
  104. static void swap_bytes(void *wordP, size_t cbSize /*must be 2, 4, 8 */)  
  105. {  
  106.     size_t   i;  
  107.     byte     t;  
  108.     for(i=0; i<cbSize/2; i++){  
  109.         t = ((byte *) wordP)[i];  
  110.         ((byte *)wordP)[i] = ((byte *) wordP)[cbSize-i-1];  
  111.         ((byte *) wordP)[cbSize-i-1] = t;  
  112.     }  
  113. }  
  114. static dword_t  dword_hton(dword_t host)  
  115. {  
  116.     if (!_rpc_is_bigendian)  
  117.         host = swap_dword_type(host);  
  118.     return  host;  
  119. }  
  120. static dword_t  dword_ntoh(dword_t net)  
  121. {  
  122.     if (!_rpc_is_bigendian)  
  123.         net = swap_dword_type(net);  
  124.     return  net;  
  125. }  
  126. static word_t   word_hton(word_t host)  
  127. {  
  128.     if (!_rpc_is_bigendian)  
  129.         host = swap_word_type(host);  
  130.     return  host;  
  131. }  
  132. static word_t   word_ntoh(word_t net)  
  133. {  
  134.     if (!_rpc_is_bigendian)  
  135.         net = swap_word_type(net);  
  136.     return  net;  
  137. }  
  138. static qword_t  qword_hton(qword_t host)  
  139. {  
  140.     if (!_rpc_is_bigendian)  
  141.         swap_bytes(&host, sizeof(qword_t));  
  142.     return  host;  
  143. }  
  144. static qword_t  qword_ntoh(qword_t net)  
  145. {  
  146.     if (!_rpc_is_bigendian)  
  147.         swap_bytes(&net, sizeof(qword_t));  
  148.     return  net;  
  149. }  
  150. static double   double_hton(double host)  
  151. {  
  152.     if (!_rpc_is_bigendian)  
  153.         swap_bytes(&host, sizeof(qword_t));  
  154.     return  host;  
  155. }  
  156. static double   double_ntoh(double net)  
  157. {  
  158.     if (!_rpc_is_bigendian)  
  159.         swap_bytes(&net, sizeof(qword_t));  
  160.     return  net;  
  161. }  
  162. static float    float_hton(float host)  
  163. {  
  164.     if (!_rpc_is_bigendian)  
  165.         swap_bytes(&host, sizeof(dword_t));  
  166.     return  host;  
  167. }  
  168. static float    float_ntoh(float net)  
  169. {  
  170.     if (!_rpc_is_bigendian)  
  171.         swap_bytes(&net, sizeof(dword_t));  
  172.     return  net;  
  173. }  
  174. /*============================================================================= 
  175.                               Private Functions 
  176.                            socket helper functions 
  177. =============================================================================*/  
  178. static int setbufsize(SOCKET s, int rcvlen /*RPC_BUFFSIZE*/int sndlen /*RPC_BUFFSIZE*/)  
  179. {  
  180.     int rcv, snd;  
  181.     int rcvl = (intsizeof(int);  
  182.     int sndl = rcvl;  
  183.     if ( getsockopt(s, SOL_SOCKET, SO_RCVBUF, (char*)&rcv, &rcvl)==SOCKET_ERROR ||  
  184.          getsockopt(s, SOL_SOCKET, SO_SNDBUF, (char*)&snd, &sndl)==SOCKET_ERROR )  
  185.         return SOCKET_ERROR;  
  186.       
  187.     if(rcv < rcvlen){  
  188.         rcv = rcvlen;  
  189.         rcvl = setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char*)&rcv, rcvl);  
  190.         assert(rcvl==0);  
  191.     }  
  192.       
  193.     if(snd < sndlen){  
  194.         snd = sndlen;     
  195.         sndl = setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char*)&snd, sndl);  
  196.         assert(sndl==0);  
  197.     }  
  198.     return 0;  
  199. }  
  200. static int sendmsg(SOCKET s, const char* msgbuf, int msglen, int flags)  
  201. {  
  202.     int ret;  
  203.     int offset = 0;  
  204.     int left = msglen;    
  205.     while (left > 0) {  
  206.         ret = send(s, &msgbuf[offset], left, flags);  
  207.         if (ret==SOCKET_ERROR || ret==0)  
  208.             return ret;       
  209.         left -= ret;  
  210.         offset += ret;  
  211.     }  
  212.     assert(offset==msglen);  
  213.     return offset;  
  214. }  
  215. static int recvmsg(SOCKET s, char* msgbuf, int buflen, int flags)  
  216. {  
  217.     int     ret;  
  218.     int     offset = 0;  
  219.     int     left = buflen;    
  220.     while (left > 0){  
  221.         ret = recv(s, &msgbuf[offset], left, flags);  
  222.         if (ret==SOCKET_ERROR || ret==0)  
  223.             return ret;  
  224.         offset += ret;  
  225.         left -= ret;  
  226.     }  
  227.     assert(offset==buflen);  
  228.     return offset;  
  229. }  
  230. static BOOL sendbulk(SOCKET s, const char* data, int dataSize, int flags, int maxmsg)  
  231. {  
  232.     int send, ret;  
  233.     int offset = 0;  
  234.     int left = dataSize;  
  235.     while (left > 0) {  
  236.         send = left>maxmsg? maxmsg:left;  
  237.         ret = sendmsg(s, &data[offset], send, flags);  
  238.         if (ret != send)  
  239.             return FALSE;  
  240.         offset += ret;  
  241.         left -= ret;  
  242.     }  
  243.     return TRUE;  
  244. }  
  245. static BOOL recvbulk(SOCKET s, char* buf, int recvlen, int flags, int maxmsg)  
  246. {  
  247.     int  recv, ret;  
  248.     int  offset = 0;  
  249.     int  left = recvlen;  
  250.     while (left > 0){  
  251.         recv = left>maxmsg? maxmsg:left;  
  252.         ret = recvmsg(s, &buf[offset], recv, flags);  
  253.         if (ret != recv)  
  254.             return FALSE;  
  255.         offset += ret;  
  256.         left -= ret;  
  257.     }  
  258.     return TRUE;  
  259. }  
  260. static LPCSTR errmsg(DWORD dwCode, LPSTR lpszMsgBuf, DWORD dwMsgBufBytes)  
  261. {  
  262.     FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,  
  263.             NULL, dwCode, 0, /* Default language */  
  264.             lpszMsgBuf,  
  265.             dwMsgBufBytes,  
  266.             NULL);  
  267.     return lpszMsgBuf;  
  268. }  
  269. static void rpc_error_clear(rpc_invoke_error *err)  
  270. {  
  271.     err->err_type = RPC_NO_ERROR;  
  272.     err->err_code = 0;  
  273.     *err->err_source = 0;  
  274.     *err->err_detail = 0;  
  275. }  
  276. // [RESM(4)|总消息字节(4)|err_type(2)|err_code(2)|err_source_size(2)|err_source_string|err_detail_size(2)|err_detail_string]   
  277. static BOOL rpc_error_short_msg(SOCKET s, char *buf, int size, rpc_invoke_error *err)  
  278. {  
  279.     int pos = 0;  
  280.     word_t w;  
  281.     ushort err_source_size = (ushort)strlen(err->err_source)+1;  
  282.     ushort err_detail_size = (ushort)strlen(err->err_detail)+1;  
  283.     ulong  msglen = 4+4+2+2+2+err_source_size+2+err_detail_size;  
  284.     *buf = 0;  
  285.     assert((ulong)size>=msglen);  
  286.     buf[pos++] = 'R';  
  287.     buf[pos++] = 'E';  
  288.     buf[pos++] = 'S';  
  289.     buf[pos++] = 'M';  
  290.       
  291.     msglen = dword_hton(msglen);  
  292.     memcpy(buf+pos, &msglen, 4);  
  293.     pos += 4;  
  294.     w = word_hton((word_t)err->err_type);  
  295.     memcpy(buf+pos, &w, 2);  
  296.     pos += 2;  
  297.     w = word_hton((word_t)err->err_code);  
  298.     memcpy(buf+pos, &w, 2);  
  299.     pos += 2;  
  300.     w = word_hton((word_t)err_source_size);  
  301.     memcpy(buf+pos, &w, 2);  
  302.     pos += 2;     
  303.     memcpy(buf+pos, err->err_source, err_source_size);  
  304.     pos += err_source_size;  
  305.     w = word_hton((word_t)err_detail_size);  
  306.     memcpy(buf+pos, &w, 2);  
  307.     pos += 2;  
  308.     memcpy(buf+pos, err->err_detail, err_detail_size);  
  309.     pos += err_detail_size;  
  310.     assert((ulong)pos == dword_ntoh(msglen));  
  311.     if (pos == (ulong)sendmsg(s, buf, pos, 0))  
  312.         return TRUE;  
  313.     err->err_type = RPC_SOCKET_ERROR;  
  314.     err->err_code = WSAGetLastError();  
  315.     *err->err_source = 0;  
  316.     errmsg(err->err_code, err->err_detail, RPC_ERROR_STRING_LEN);  
  317.       
  318.     return FALSE;  
  319. }  
  320. static void debug_out(const char *debug_file, const char *fmt, ...)  
  321. {  
  322. #ifdef _DEBUG   
  323.     FILE *fp = 0;  
  324.     va_list ap;  
  325.       
  326.     fopen_s(&fp, debug_file, "a+");  
  327.     assert(fp);  
  328.       
  329.     va_start(ap, fmt);  
  330.     vfprintf(fp, fmt, ap);  
  331.     va_end(ap);  
  332.     fclose(fp);  
  333. #endif   
  334. }  
  335. /*============================================================================ 
  336.                        RPC PUBLIC FUNCTIONS 
  337.  ============================================================================*/  
  338. /** 
  339.  * rpc_throw_error 
  340.  */  
  341. RPCRESULT rpc_throw_error(RPC_ERROR_TYPE err_type, LONG err_code, const char* err_source, rpc_invoke_error *err);  
  342. /** 
  343.  * rpc_invoke_free 
  344.  *   创建RPC调用描述符 
  345.  */  
  346. rpc_invoke_descriptor* rpc_invoke_create(rpc_invoke_descriptor **inv, ushort ordinal, ushort num_params);  
  347. /** 
  348.  * rpc_invoke_init 
  349.  *   初始化RPC调用描述符 
  350.  */  
  351. rpc_invoke_descriptor *  
  352. rpc_invoke_init(rpc_invoke_descriptor *inv, ushort ordinal, ushort num_params);  
  353. /** 
  354.  * rpc_invoke_clear_all 
  355.  *   清除RPC调用描述符, 此后RPC调用描述符可以重新绑定变量 
  356.  */  
  357. void rpc_invoke_clear_all(rpc_invoke_descriptor *inv);  
  358. /** 
  359.  * rpc_invoke_free 
  360.  *   删除RPC调用描述符, 此后RPC调用描述符将不可用 
  361.  */  
  362. void rpc_invoke_free(rpc_invoke_descriptor *inv);  
  363. /** 
  364.  * rpc_invoke_set_param 
  365.  *   设置指定的参数, 返回参数指针 
  366.  */  
  367. rpc_param_descriptor* rpc_invoke_set_param(rpc_invoke_descriptor *inv, ushort id, word_t type);  
  368. /** 
  369.  * rpc_param_clear 
  370.  *   清除参数内容 
  371.  */  
  372. void rpc_param_clear(rpc_param_descriptor *param);  
  373. /** 
  374.  * rpc_param_free_list 
  375.  *   清除参数列表内容 
  376.  */  
  377. void rpc_param_free_list(rpc_param_descriptor *param_list, word_t num_params);  
  378. /** 
  379.  * rpc_connection_create 
  380.  *   创建RPC连接 
  381.  */  
  382. RPCRESULT rpc_connection_create(rpc_connection_descriptor **conn, const char *host, const char *port, long rcvtimeo, rpc_invoke_error *err);  
  383. /** 
  384.  * rpc_connection_free 
  385.  *   清除RPC连接 
  386.  */  
  387. void rpc_connection_free(rpc_connection_descriptor *conn);  
  388. /** 
  389.  * rpc_connection_set 
  390.  *   设置RPC连接的属性 
  391.  */  
  392. void rpc_connection_set(rpc_connection_descriptor *conn, dword_t token, dword_t timeout, byte encheader, byte encpackage);  
  393. /** 
  394.  * rpc_connection_free 
  395.  *   设置输入的参数, 返回参数指针 
  396.  */  
  397. rpc_param_descriptor* rpc_invoke_bind_param(rpc_invoke_descriptor *inv, ushort id, word_t type, void *vaddr, size_t array_size, BOOL is_owner);  
  398. /** 
  399.  * rpc_connection_free 
  400.  *   计算参数字节总数 
  401.  */  
  402. dword_t rpc_param_get_size(rpc_param_descriptor *param);  
  403. /** 
  404.  * rpc_connection_free 
  405.  *   计算调用消息的字节总数 
  406.  */  
  407. dword_t rpc_invoke_get_size(rpc_invoke_descriptor *inv);  
  408. /** 
  409.  * rpc_invoke_marshal 
  410.  *   列集全部数据到totalBuf中 
  411.  */  
  412. int rpc_invoke_marshal(rpc_invoke_descriptor *inv, char *totalBuf, int totalSize);  
  413. /** 
  414.  * rpc_invokehdr_unmarshal 
  415.  *   散集调用头 
  416.  */  
  417. RPCRESULT rpc_invokehdr_unmarshal(SOCKET sClient, dword_t dwToken, char *rpcHdr, int hdrSize, rpc_invoke_descriptor *inv, rpc_invoke_error *err);  
  418. /** 
  419.  * rpc_invoke_unmarshal 
  420.  *   散集数据到参数中 
  421.  */  
  422. RPCRESULT rpc_invoke_unmarshal(rpc_invoke_descriptor *inv,   
  423.                                char                  *totalBuf,   
  424.                                size_t                 totalSize,  
  425.                                rpc_param_descriptor **out_params,  
  426.                                word_t                *num_params,  
  427.                                rpc_invoke_error      *err);  
  428. /** 
  429.  * rpc_param_get_short 
  430.  *   取得短整数参数值 
  431.  */  
  432. void rpc_param_get_short (rpc_param_descriptor *param, SHORT *val);  
  433. /** 
  434.  * rpc_param_get_ushort 
  435.  *   取得短整数参数值 
  436.  */  
  437. void rpc_param_get_ushort (rpc_param_descriptor *param, USHORT *val);  
  438. /** 
  439.  * rpc_param_get_long 
  440.  *   取得整数参数值 
  441.  */  
  442. void rpc_param_get_long (rpc_param_descriptor *param, LONG *val);  
  443. /** 
  444.  * rpc_param_get_ulong 
  445.  *   取得无符号整数参数值 
  446.  */  
  447. void rpc_param_get_ulong (rpc_param_descriptor *param, ULONG *val);  
  448. /** 
  449.  * rpc_param_get_int 
  450.  *   取得整数参数值 
  451.  */  
  452. void rpc_param_get_int (rpc_param_descriptor *param, INT *val);  
  453. /** 
  454.  * rpc_param_get_double 
  455.  *   取得双精度参数值 
  456.  */  
  457. void rpc_param_get_double (rpc_param_descriptor *param, double *val);  
  458. /** 
  459.  * rpc_invoke_send 
  460.  *   发送数据 
  461.  */  
  462. RPCRESULT rpc_invoke_send(rpc_connection_descriptor *conn, rpc_invoke_descriptor *inv, rpc_invoke_error *err);  
  463. /** 
  464.  * rpc_invoke_recv 
  465.  *   接收数据 
  466.  */  
  467. RPCRESULT rpc_invoke_recv(rpc_connection_descriptor *conn, rpc_invoke_descriptor *outv, rpc_invoke_error *err);  
  468. /** 
  469.  * rpc_connection_free 
  470.  *   执行RPC调用 
  471.  */  
  472. RPCRESULT rpc_invoke_execute(rpc_connection_descriptor *conn,   
  473.                              rpc_invoke_descriptor     *inv,   
  474.                              rpc_invoke_descriptor     *outv,   
  475.                              rpc_invoke_error          *err);  
  476. #ifdef __cplusplus   
  477. }  
  478. #endif   
  479. #endif /* _RPCAPI_H__ */  
/** * rpcapi.h -cheungmine@gmail.com * all rights reserved 2009 */ #ifndef _RPCAPI_H__ #define _RPCAPI_H__ #include <winsock2.h> #pragma comment(lib, "ws2_32.lib") #include <process.h> /* _beginthreadex, _endthread */ #include "../rc4/unistd.h" #include "../rc4/md5.h" #include "../rc4/rc4.h" #include "rpctype.h" #include "rpcerr.h" #ifdef __cplusplus extern "C" { #endif static BOOL _rpc_is_bigendian = (('4321'>>24)=='1'); #define PARAMVALUE(pl,i,type) ((type)(*((type*) pl[i].param_bytes))) typedef enum { RPC_ENCHEADER_BIT = 0, RPC_ENCPACKAGE_BIT = 1, RPC_BIGENDIAN_BIT = 7 }RPC_BITFLAG_ENUM; /** * param descriptor */ #define RPC_PARAM_HEADER_SIZE 16 typedef struct _rpc_param_descriptor { word_t param_type; // 参数类型:变量类型或结构类型 word_t size_type; // 参数类型尺寸字节 size_t array_size; // 数组元素数目: 0 不是数组; >0数组 size_t param_size; // 参数数据字节数=参数类型尺寸字节*元素数目 void *param_bytes; // 指向参数数据的指针的引用, 不复制数据 BOOL is_owner; // 是否拥有数据. 如果为TRUE, 需要free(param_bytes) }rpc_param_descriptor; /** * invoke descriptor */ #define RPC_INVOKE_HEADER_SIZE 24 /* 不可以更改 */ typedef struct _rpc_invoke_descriptor { /* 24字节头 + 内容 * ['RCmn'(4)|用户标识(4)|总消息字节(4)|标志(2)| 保留(2)|原始字节数(4)|方法序号(2)|参数数目(2)] */ dword_t totalBytes; // 总消息字节4 word_t bitsFlag; // 标志位2: [7=BigEndian] word_t reserved; // 保留2 dword_t result; // 返回值 // 内部值, 调用时,需要列集在bitsFlag中 dword_t invToken; byte bigEndian; byte encHdr; byte encPkg; // 如果压缩或加密, 从以下位置内容开始 ushort ordinal; // 方法序号2 ushort num_params; // 参数数目 rpc_param_descriptor *params_list; // 参数列表 // 做为输入时, 存放临时值 // char *pbBuf; union{ char bVal; long lVal; short sVal; float fVal; double dVal; __int64 llVal; }; }rpc_invoke_descriptor; /** * connection descriptor */ typedef struct _rpc_connection_descriptor { BOOL is_bigendian; // 字节顺序 dword_t token; // 调用标识 dword_t timeout; // 超时 byte enc_hdr; // 头加密标志 byte enc_pkg; // 参数包加密标志 SOCKET stream; // SOCKET 连接 char host[130]; // 主机名或IP地址 char port[6]; // 端口号 rpc_invoke_error last_err; // 最近的错误 char buffer[RPC_BUFFSIZE]; // 网络传输缓冲区 }rpc_connection_descriptor; /*============================================================================= Private Functions host byte order and network byte order transform =============================================================================*/ static int SafeStringSize(const char* psz) { return (int)(psz? (strlen(psz)+1):0); } /** * More fast than swap_bytes(...) for handle word and dword type */ #define swap_word_type(x) ((WORD)(((((WORD)(x))&0x00ff)<<8)|((((WORD)(x))&0xff00)>>8))) #define swap_dword_type(x) ((DWORD)(((((DWORD)(x))&0xff000000)>>24)|((((DWORD)(x))&0x00ff0000)>>8)|((((DWORD)(x))&0x0000ff00)<<8)|((((DWORD)(x))&0x000000ff)<<24))) static void swap_bytes(void *wordP, size_t cbSize /*must be 2, 4, 8 */) { size_t i; byte t; for(i=0; i<cbSize/2; i++){ t = ((byte *) wordP)[i]; ((byte *)wordP)[i] = ((byte *) wordP)[cbSize-i-1]; ((byte *) wordP)[cbSize-i-1] = t; } } static dword_t dword_hton(dword_t host) { if (!_rpc_is_bigendian) host = swap_dword_type(host); return host; } static dword_t dword_ntoh(dword_t net) { if (!_rpc_is_bigendian) net = swap_dword_type(net); return net; } static word_t word_hton(word_t host) { if (!_rpc_is_bigendian) host = swap_word_type(host); return host; } static word_t word_ntoh(word_t net) { if (!_rpc_is_bigendian) net = swap_word_type(net); return net; } static qword_t qword_hton(qword_t host) { if (!_rpc_is_bigendian) swap_bytes(&host, sizeof(qword_t)); return host; } static qword_t qword_ntoh(qword_t net) { if (!_rpc_is_bigendian) swap_bytes(&net, sizeof(qword_t)); return net; } static double double_hton(double host) { if (!_rpc_is_bigendian) swap_bytes(&host, sizeof(qword_t)); return host; } static double double_ntoh(double net) { if (!_rpc_is_bigendian) swap_bytes(&net, sizeof(qword_t)); return net; } static float float_hton(float host) { if (!_rpc_is_bigendian) swap_bytes(&host, sizeof(dword_t)); return host; } static float float_ntoh(float net) { if (!_rpc_is_bigendian) swap_bytes(&net, sizeof(dword_t)); return net; } /*============================================================================= Private Functions socket helper functions =============================================================================*/ static int setbufsize(SOCKET s, int rcvlen /*RPC_BUFFSIZE*/, int sndlen /*RPC_BUFFSIZE*/) { int rcv, snd; int rcvl = (int) sizeof(int); int sndl = rcvl; if ( getsockopt(s, SOL_SOCKET, SO_RCVBUF, (char*)&rcv, &rcvl)==SOCKET_ERROR || getsockopt(s, SOL_SOCKET, SO_SNDBUF, (char*)&snd, &sndl)==SOCKET_ERROR ) return SOCKET_ERROR; if(rcv < rcvlen){ rcv = rcvlen; rcvl = setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char*)&rcv, rcvl); assert(rcvl==0); } if(snd < sndlen){ snd = sndlen; sndl = setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char*)&snd, sndl); assert(sndl==0); } return 0; } static int sendmsg(SOCKET s, const char* msgbuf, int msglen, int flags) { int ret; int offset = 0; int left = msglen; while (left > 0) { ret = send(s, &msgbuf[offset], left, flags); if (ret==SOCKET_ERROR || ret==0) return ret; left -= ret; offset += ret; } assert(offset==msglen); return offset; } static int recvmsg(SOCKET s, char* msgbuf, int buflen, int flags) { int ret; int offset = 0; int left = buflen; while (left > 0){ ret = recv(s, &msgbuf[offset], left, flags); if (ret==SOCKET_ERROR || ret==0) return ret; offset += ret; left -= ret; } assert(offset==buflen); return offset; } static BOOL sendbulk(SOCKET s, const char* data, int dataSize, int flags, int maxmsg) { int send, ret; int offset = 0; int left = dataSize; while (left > 0) { send = left>maxmsg? maxmsg:left; ret = sendmsg(s, &data[offset], send, flags); if (ret != send) return FALSE; offset += ret; left -= ret; } return TRUE; } static BOOL recvbulk(SOCKET s, char* buf, int recvlen, int flags, int maxmsg) { int recv, ret; int offset = 0; int left = recvlen; while (left > 0){ recv = left>maxmsg? maxmsg:left; ret = recvmsg(s, &buf[offset], recv, flags); if (ret != recv) return FALSE; offset += ret; left -= ret; } return TRUE; } static LPCSTR errmsg(DWORD dwCode, LPSTR lpszMsgBuf, DWORD dwMsgBufBytes) { FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwCode, 0, /* Default language */ lpszMsgBuf, dwMsgBufBytes, NULL); return lpszMsgBuf; } static void rpc_error_clear(rpc_invoke_error *err) { err->err_type = RPC_NO_ERROR; err->err_code = 0; *err->err_source = 0; *err->err_detail = 0; } // [RESM(4)|总消息字节(4)|err_type(2)|err_code(2)|err_source_size(2)|err_source_string|err_detail_size(2)|err_detail_string] static BOOL rpc_error_short_msg(SOCKET s, char *buf, int size, rpc_invoke_error *err) { int pos = 0; word_t w; ushort err_source_size = (ushort)strlen(err->err_source)+1; ushort err_detail_size = (ushort)strlen(err->err_detail)+1; ulong msglen = 4+4+2+2+2+err_source_size+2+err_detail_size; *buf = 0; assert((ulong)size>=msglen); buf[pos++] = 'R'; buf[pos++] = 'E'; buf[pos++] = 'S'; buf[pos++] = 'M'; msglen = dword_hton(msglen); memcpy(buf+pos, &msglen, 4); pos += 4; w = word_hton((word_t)err->err_type); memcpy(buf+pos, &w, 2); pos += 2; w = word_hton((word_t)err->err_code); memcpy(buf+pos, &w, 2); pos += 2; w = word_hton((word_t)err_source_size); memcpy(buf+pos, &w, 2); pos += 2; memcpy(buf+pos, err->err_source, err_source_size); pos += err_source_size; w = word_hton((word_t)err_detail_size); memcpy(buf+pos, &w, 2); pos += 2; memcpy(buf+pos, err->err_detail, err_detail_size); pos += err_detail_size; assert((ulong)pos == dword_ntoh(msglen)); if (pos == (ulong)sendmsg(s, buf, pos, 0)) return TRUE; err->err_type = RPC_SOCKET_ERROR; err->err_code = WSAGetLastError(); *err->err_source = 0; errmsg(err->err_code, err->err_detail, RPC_ERROR_STRING_LEN); return FALSE; } static void debug_out(const char *debug_file, const char *fmt, ...) { #ifdef _DEBUG FILE *fp = 0; va_list ap; fopen_s(&fp, debug_file, "a+"); assert(fp); va_start(ap, fmt); vfprintf(fp, fmt, ap); va_end(ap); fclose(fp); #endif } /*============================================================================ RPC PUBLIC FUNCTIONS ============================================================================*/ /** * rpc_throw_error */ RPCRESULT rpc_throw_error(RPC_ERROR_TYPE err_type, LONG err_code, const char* err_source, rpc_invoke_error *err); /** * rpc_invoke_free * 创建RPC调用描述符 */ rpc_invoke_descriptor* rpc_invoke_create(rpc_invoke_descriptor **inv, ushort ordinal, ushort num_params); /** * rpc_invoke_init * 初始化RPC调用描述符 */ rpc_invoke_descriptor * rpc_invoke_init(rpc_invoke_descriptor *inv, ushort ordinal, ushort num_params); /** * rpc_invoke_clear_all * 清除RPC调用描述符, 此后RPC调用描述符可以重新绑定变量 */ void rpc_invoke_clear_all(rpc_invoke_descriptor *inv); /** * rpc_invoke_free * 删除RPC调用描述符, 此后RPC调用描述符将不可用 */ void rpc_invoke_free(rpc_invoke_descriptor *inv); /** * rpc_invoke_set_param * 设置指定的参数, 返回参数指针 */ rpc_param_descriptor* rpc_invoke_set_param(rpc_invoke_descriptor *inv, ushort id, word_t type); /** * rpc_param_clear * 清除参数内容 */ void rpc_param_clear(rpc_param_descriptor *param); /** * rpc_param_free_list * 清除参数列表内容 */ void rpc_param_free_list(rpc_param_descriptor *param_list, word_t num_params); /** * rpc_connection_create * 创建RPC连接 */ RPCRESULT rpc_connection_create(rpc_connection_descriptor **conn, const char *host, const char *port, long rcvtimeo, rpc_invoke_error *err); /** * rpc_connection_free * 清除RPC连接 */ void rpc_connection_free(rpc_connection_descriptor *conn); /** * rpc_connection_set * 设置RPC连接的属性 */ void rpc_connection_set(rpc_connection_descriptor *conn, dword_t token, dword_t timeout, byte encheader, byte encpackage); /** * rpc_connection_free * 设置输入的参数, 返回参数指针 */ rpc_param_descriptor* rpc_invoke_bind_param(rpc_invoke_descriptor *inv, ushort id, word_t type, void *vaddr, size_t array_size, BOOL is_owner); /** * rpc_connection_free * 计算参数字节总数 */ dword_t rpc_param_get_size(rpc_param_descriptor *param); /** * rpc_connection_free * 计算调用消息的字节总数 */ dword_t rpc_invoke_get_size(rpc_invoke_descriptor *inv); /** * rpc_invoke_marshal * 列集全部数据到totalBuf中 */ int rpc_invoke_marshal(rpc_invoke_descriptor *inv, char *totalBuf, int totalSize); /** * rpc_invokehdr_unmarshal * 散集调用头 */ RPCRESULT rpc_invokehdr_unmarshal(SOCKET sClient, dword_t dwToken, char *rpcHdr, int hdrSize, rpc_invoke_descriptor *inv, rpc_invoke_error *err); /** * rpc_invoke_unmarshal * 散集数据到参数中 */ RPCRESULT rpc_invoke_unmarshal(rpc_invoke_descriptor *inv, char *totalBuf, size_t totalSize, rpc_param_descriptor **out_params, word_t *num_params, rpc_invoke_error *err); /** * rpc_param_get_short * 取得短整数参数值 */ void rpc_param_get_short (rpc_param_descriptor *param, SHORT *val); /** * rpc_param_get_ushort * 取得短整数参数值 */ void rpc_param_get_ushort (rpc_param_descriptor *param, USHORT *val); /** * rpc_param_get_long * 取得整数参数值 */ void rpc_param_get_long (rpc_param_descriptor *param, LONG *val); /** * rpc_param_get_ulong * 取得无符号整数参数值 */ void rpc_param_get_ulong (rpc_param_descriptor *param, ULONG *val); /** * rpc_param_get_int * 取得整数参数值 */ void rpc_param_get_int (rpc_param_descriptor *param, INT *val); /** * rpc_param_get_double * 取得双精度参数值 */ void rpc_param_get_double (rpc_param_descriptor *param, double *val); /** * rpc_invoke_send * 发送数据 */ RPCRESULT rpc_invoke_send(rpc_connection_descriptor *conn, rpc_invoke_descriptor *inv, rpc_invoke_error *err); /** * rpc_invoke_recv * 接收数据 */ RPCRESULT rpc_invoke_recv(rpc_connection_descriptor *conn, rpc_invoke_descriptor *outv, rpc_invoke_error *err); /** * rpc_connection_free * 执行RPC调用 */ RPCRESULT rpc_invoke_execute(rpc_connection_descriptor *conn, rpc_invoke_descriptor *inv, rpc_invoke_descriptor *outv, rpc_invoke_error *err); #ifdef __cplusplus } #endif #endif /* _RPCAPI_H__ */

 

 

rpcapi.c如下:

  1. /** 
  2.  * rpcapi.c -cheungmine@gmail.com 
  3.  */  
  4. #include "rpcapi.h"   
  5. // 打开socket   
  6. static RPCRESULT opensocket(SOCKET *pStream, const char *lpszServer, int nPort, rpc_invoke_error *pError)  
  7. {  
  8.     struct sockaddr_in   server;  
  9.     struct hostent      *hp = 0;  
  10.     unsigned int         iAddr;  
  11.       
  12.     *pStream = INVALID_SOCKET;  
  13.     // Parse server host   
  14.     if(inet_addr(lpszServer) == INADDR_NONE){  
  15.         hp = gethostbyname(lpszServer);  
  16.         if(hp==0)  
  17.             return rpc_throw_error(RPC_USER_ERROR, RPC_INVALID_HOST, "opensocket()", pError);  
  18.         server.sin_addr.s_addr = *((unsigned long*)hp->h_addr);  
  19.     }  
  20.     else{  
  21.         iAddr = inet_addr(lpszServer);  
  22.         server.sin_addr.s_addr = iAddr;  
  23.       
  24.         // too slow to use gethostbyaddr   
  25.     //OLD:  hp = gethostbyaddr((char*)&iAddr, sizeof(iAddr), AF_INET);   
  26.     //OLD:  if(hp==0)   
  27.     //OLD:      return rpc_throw_error(RPC_USER_ERROR, RPC_INVALID_HOST, "opensocket()", pError);   
  28.     //OLD:  server.sin_addr.s_addr = *((unsigned long*)hp->h_addr);   
  29.     }  
  30.     server.sin_family = AF_INET;  
  31.     server.sin_port = htons((u_short)nPort);  
  32.     // Create a new socket and attempt to connect to server   
  33.     (*pStream) = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);  
  34.     if ((*pStream) == INVALID_SOCKET)  
  35.         return rpc_throw_error(RPC_SOCKET_ERROR, WSAGetLastError(), "socket()", pError);  
  36.     // Make a connection to the server   
  37.     if (connect((*pStream), (struct sockaddr *) &server, sizeof(server))==SOCKET_ERROR){  
  38.         closesocket( *pStream );  
  39.         *pStream = INVALID_SOCKET;  
  40.         return rpc_throw_error(RPC_SOCKET_ERROR, WSAGetLastError(), "connect()", pError);  
  41.     }  
  42.     setbufsize(*pStream, RPC_BUFFSIZE, RPC_BUFFSIZE);  
  43.     return RPC_SUCCESS;  
  44. }  
  45. // 列集参数   
  46. static int rpc_param_marshal(rpc_param_descriptor *param, char *buf)  
  47. {  
  48.     word_t   w;  
  49.     dword_t  dw;  
  50.     int pos = 0;  
  51.     // 参数头RPC_PARAM_HEADER_SIZE字节:   
  52.     //   [参数类型(2)|类型字节(2)|数组元素数目(4)|参数数据字节数(4)|参数成员数(2)=0|保留(2)=0]   
  53.     w = word_hton(param->param_type);  
  54.     memcpy(buf+pos, &w, 2);  
  55.     pos += 2;  
  56.     w = word_hton(param->size_type);  
  57.     memcpy(buf+pos, &w, 2);  
  58.     pos += 2;  
  59.       
  60.     dw = dword_hton((dword_t)param->array_size);  
  61.     memcpy(buf+pos, &dw, 4);  
  62.     pos += 4;  
  63.     dw = dword_hton((dword_t)param->param_size);  
  64.     memcpy(buf+pos, &dw, 4);  
  65.     pos += 4;  
  66.     w = 0;  
  67.     memcpy(buf+pos, &w, 2);  
  68.     pos += 2;  
  69.     w = 0;  
  70.     memcpy(buf+pos, &w, 2);  
  71.     pos += 2;  
  72.     // 参数的数据   
  73.     memcpy(buf+pos, param->param_bytes, param->param_size);  
  74.     pos += (int)param->param_size;  
  75.     return pos;  
  76. }  
  77. // 散集参数   
  78. // 参数头RPC_PARAM_HEADER_SIZE字节:   
  79. //   [参数类型(2)|类型字节(2)|数组元素数目(4)|参数数据字节数(4)|参数成员数(2)|保留(2)=0]   
  80. static size_t rpc_param_unmarshal(BOOL marshal_bigendian, rpc_param_descriptor *param, char *buf)  
  81. {  
  82.     byte   *pcb;  
  83.     size_t  i;  
  84.     size_t  pos = 0;  
  85.     assert(param->array_size==0||param->array_size==param->param_size/param->size_type);  
  86.     // 参数类型   
  87.     param->param_type = word_ntoh(*((word_t*)(buf+pos)));  
  88.     pos += 2;  
  89.     param->size_type = word_ntoh(*((word_t*)(buf+pos)));  
  90.     pos += 2;  
  91.     param->array_size = dword_ntoh(*((dword_t*)(buf+pos)));  
  92.     pos += 4;  
  93.     param->param_size = dword_ntoh(*((dword_t*)(buf+pos)));  
  94.     pos += 4;  
  95.     // 参数成员   
  96.     pos += 2;  
  97.     // 保留值   
  98.     pos += 2;  
  99.     // 参数字节指针   
  100.     // 这里假设列集方marshal_bigendian和散集方_rpc_is_bigendian的字节次序一致,    
  101.     // 以后要添加代码处理不一致的情况   
  102.     if (param->param_size==0){  
  103.         param->param_bytes = 0;  
  104.         return pos;  
  105.     }  
  106.     if (param->size_type==1 || marshal_bigendian==_rpc_is_bigendian){  
  107.         param->param_bytes = (void*)(buf+pos);  
  108.         return (pos + param->param_size);  
  109.     }  
  110.       
  111.     // 必须交换字节次序   
  112.     //   
  113.     assert(param->size_type==2||param->size_type==4||param->size_type==8);  
  114.     assert(marshal_bigendian != _rpc_is_bigendian);  
  115.     param->param_bytes = (void*)(buf+pos);  
  116.     pcb = (buf+pos);  
  117.       
  118.     i = param->param_size/param->size_type;  
  119.     while(i-->0){  
  120.         swap_bytes(&pcb[i*param->size_type], param->size_type);  
  121.     }  
  122.     assert(i==-1);  
  123.     return (pos + param->param_size);  
  124. }  
  125. void rpc_param_get_ushort (rpc_param_descriptor *param, USHORT *val)  
  126. {  
  127.     assert(param && param->param_bytes && param->array_size==0 &&   
  128.            param->param_type==RPCT_USHORT && param->size_type==RPC_TYPE_SIZE(RPCT_USHORT));  
  129.       
  130.     *val = *((USHORT*)(param->param_bytes));  
  131. }  
  132. void rpc_param_get_short (rpc_param_descriptor *param, SHORT *val)  
  133. {  
  134.     assert(param && param->param_bytes && param->array_size==0 &&   
  135.            param->param_type==RPCT_SHORT && param->size_type==RPC_TYPE_SIZE(RPCT_SHORT));  
  136.       
  137.     *val = *((SHORT*)(param->param_bytes));  
  138. }  
  139. void rpc_param_get_long (rpc_param_descriptor *param, LONG *val)  
  140. {  
  141.     assert(param && param->param_bytes && param->array_size==0 &&   
  142.            param->param_type==RPCT_LONG && param->size_type==RPC_TYPE_SIZE(RPCT_LONG));  
  143.       
  144.     *val = *((LONG*)(param->param_bytes));  
  145. }  
  146. void rpc_param_get_int (rpc_param_descriptor *param, INT *val)  
  147. {  
  148.     assert(param && param->param_bytes && param->array_size==0 &&   
  149.            param->param_type==RPCT_INT && param->size_type==RPC_TYPE_SIZE(RPCT_INT));  
  150.       
  151.     *val = *((INT*)(param->param_bytes));  
  152. }  
  153. void rpc_param_get_ulong (rpc_param_descriptor *param, ULONG *val)  
  154. {  
  155.     assert(param && param->param_bytes && param->array_size==0 &&   
  156.            param->param_type==RPCT_ULONG && param->size_type==RPC_TYPE_SIZE(RPCT_ULONG));  
  157.       
  158.     *val = *((ULONG*)(param->param_bytes));  
  159. }  
  160. void rpc_param_get_double (rpc_param_descriptor *param, DOUBLE *val)  
  161. {  
  162.     assert(param && param->param_bytes && param->array_size==0 &&   
  163.            param->param_type==RPCT_DOUBLE && param->size_type==RPC_TYPE_SIZE(RPCT_DOUBLE));  
  164.       
  165.     *val = *((DOUBLE*)(param->param_bytes));  
  166. }  
  167. RPCRESULT rpc_invoke_send(rpc_connection_descriptor *conn, rpc_invoke_descriptor *inv, rpc_invoke_error *err)  
  168. {  
  169.     BOOL       br;  
  170.     char      *buffer = 0;  
  171.     dword_t    cbTotal = 0;  
  172.       
  173.     cbTotal = rpc_invoke_get_size(inv);  
  174.           
  175.     // 既然<=RPC_BUFFSIZE, 则使用默认的buffer   
  176.     if (cbTotal <= RPC_BUFFSIZE){  
  177.         cbTotal = rpc_invoke_marshal(inv, conn->buffer, cbTotal);  
  178.         assert(cbTotal != -1);  
  179.               
  180.         if (cbTotal != sendmsg(conn->stream, conn->buffer, cbTotal, 0))  
  181.             return rpc_throw_error(RPC_SOCKET_ERROR, WSAGetLastError(), "rpc_invoke_send()", err);  
  182.         else  
  183.             return RPC_SUCCESS;  
  184.     }  
  185.     else {  
  186.         buffer = malloc(cbTotal);  
  187.           
  188.         // 内存分配失败   
  189.         if (!buffer)  
  190.             return rpc_throw_error(RPC_SYSTEM_ERROR, GetLastError(), "rpc_invoke_send()", err);  
  191.           
  192.         cbTotal = rpc_invoke_marshal(inv, buffer, cbTotal);  
  193.         assert(cbTotal != -1);  
  194.           
  195.         // 发送大块数据   
  196.         br = sendbulk(conn->stream, buffer, cbTotal, 0, RPC_BUFFSIZE);  
  197.         FREE_S(buffer)  
  198.         if (!br)  
  199.             return rpc_throw_error(RPC_SOCKET_ERROR, WSAGetLastError(), "rpc_invoke_send()", err);  
  200.         else  
  201.             return RPC_SUCCESS;  
  202.     }  
  203. }  
  204. RPCRESULT rpc_invoke_recv(rpc_connection_descriptor *conn, rpc_invoke_descriptor *outv, rpc_invoke_error *err)  
  205. {  
  206.     RPCRESULT  res;  
  207.     // 接收头   
  208.     res = rpc_invokehdr_unmarshal(conn->stream, conn->token, conn->buffer, RPC_INVOKE_HEADER_SIZE, outv, err);  
  209.     if (RPC_SUCCESS != res)  
  210.         return res;  
  211.     // 验证token   
  212.     if (conn->token != outv->invToken)  
  213.         return rpc_throw_error(RPC_USER_ERROR, RPC_INVALIDMSG, "rpc_invoke_recv()", err);  
  214.     // 接收其余全部数据   
  215.     if (outv->totalBytes > RPC_BUFFSIZE){  
  216.         MALLOC_S(outv->pbBuf, outv->totalBytes, char);  
  217.         memcpy(outv->pbBuf, conn->buffer, RPC_INVOKE_HEADER_SIZE);  
  218.     }  
  219.     else{  
  220.         outv->pbBuf = conn->buffer;  
  221.     }  
  222.     assert(outv->pbBuf);  
  223.     if (!recvbulk(conn->stream, outv->pbBuf+RPC_INVOKE_HEADER_SIZE, outv->totalBytes-RPC_INVOKE_HEADER_SIZE, 0, RPC_BUFFSIZE)){  
  224.         if (outv->pbBuf != conn->buffer){  
  225.             FREE_S(outv->pbBuf)  
  226.             outv->pbBuf = 0;  
  227.         }  
  228.         return rpc_throw_error(RPC_USER_ERROR, RPC_NETWORK_ERROR, "rpc_invoke_recv()", err);  
  229.     }  
  230.     if (RPC_SUCCESS != rpc_invoke_unmarshal(outv, outv->pbBuf, outv->totalBytes, &outv->params_list, &outv->num_params, err)){  
  231.         if (outv->pbBuf != conn->buffer){  
  232.             FREE_S(outv->pbBuf)  
  233.             outv->pbBuf = 0;  
  234.         }  
  235.         return rpc_throw_error(RPC_USER_ERROR, RPC_INVALIDMSG, "rpc_invoke_recv()", err);  
  236.     }  
  237.     return RPC_SUCCESS;  
  238. }  
  239. /*============================================================================= 
  240.                               Public Functions 
  241.                       Remote Procedure Call Impementation 
  242. =============================================================================*/  
  243. rpc_invoke_descriptor*  
  244. rpc_invoke_create(rpc_invoke_descriptor **inv, ushort ordinal, ushort num_params)  
  245. {     
  246.     assert(inv);  
  247.     MALLOC_S(*inv, 1, rpc_invoke_descriptor)  
  248.     assert(*inv);  
  249.       
  250.     (*inv)->bigEndian = _rpc_is_bigendian;  
  251.     (*inv)->ordinal = ordinal;  
  252.     (*inv)->num_params = num_params;  
  253.           
  254.     MALLOC_S((*inv)->params_list, num_params, rpc_param_descriptor)  
  255.           
  256.     return (*inv);  
  257. }  
  258. rpc_invoke_descriptor *  
  259. rpc_invoke_init(rpc_invoke_descriptor *inv, ushort ordinal, ushort num_params)  
  260. {     
  261.     assert(inv);  
  262.     rpc_invoke_clear_all(inv);  
  263.     inv->ordinal = ordinal;  
  264.     inv->num_params = num_params;      
  265.     MALLOC_S(inv->params_list, num_params, rpc_param_descriptor)  
  266.     return inv;  
  267. }  
  268. void rpc_invoke_clear_all(rpc_invoke_descriptor *inv)  
  269. {  
  270.     assert(inv);  
  271.     if (inv->pbBuf && inv->totalBytes>RPC_BUFFSIZE){  
  272.         FREE_S(inv->pbBuf)  
  273.         assert(inv->pbBuf==0);  
  274.     }  
  275.     rpc_param_free_list(inv->params_list, inv->num_params);  
  276.     memset(inv, 0, sizeof(rpc_invoke_descriptor));  
  277.     inv->bigEndian = _rpc_is_bigendian? 1:0;  
  278. }  
  279. void rpc_invoke_free(rpc_invoke_descriptor *inv)  
  280. {  
  281.     rpc_invoke_clear_all(inv);  
  282.     FREE_S(inv)  
  283. }  
  284. rpc_param_descriptor* rpc_invoke_bind_param(rpc_invoke_descriptor *inv, ushort id, word_t type, void *vaddr, size_t array_size, BOOL is_owner)  
  285. {  
  286.     rpc_param_descriptor* p;  
  287.     assert(id>=0 && id<inv->num_params);  
  288.     p = &inv->params_list[id];  
  289.     p->param_type = type;  
  290.     p->size_type = RPC_TYPE_SIZE(type);    
  291.     p->array_size = array_size;  
  292.     p->param_bytes = vaddr;      // may be NULL   
  293.     if (type == RPCT_STRING)  
  294.         p->param_size = array_size;  
  295.     else  
  296.         p->param_size = p->size_type * (array_size > 0? array_size : 1);  
  297.           
  298.     p->is_owner = is_owner;  
  299.     return p;  
  300. }  
  301. void rpc_param_clear(rpc_param_descriptor *p)  
  302. {  
  303.     if (p->is_owner)  
  304.         FREE_S(p->param_bytes)  
  305.       
  306.     memset(p, 0, sizeof(rpc_param_descriptor));  
  307. }  
  308. void rpc_param_free_list(rpc_param_descriptor *param_list, word_t num_params)  
  309. {  
  310.     while(num_params-->0)  
  311.         rpc_param_clear(&param_list[num_params]);  
  312.     FREE_S(param_list)  
  313. }  
  314. RPCRESULT rpc_connection_create(rpc_connection_descriptor **conn, const char *host, const char *port, long rcvtimeo, rpc_invoke_error *err)  
  315. {  
  316.     WSADATA   wsd;  
  317.     struct timeval tv_out;  
  318.     int       i;  
  319.     // 加载WinSock DLL   
  320.     if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)  
  321.         return rpc_throw_error(RPC_USER_ERROR, RPC_WINSOCK_NOTFOUND, "WSAStartup()", err);  
  322.     // 创建对象   
  323.     MALLOC_S(*conn, 1, rpc_connection_descriptor)  
  324.       
  325.     // 设置字节顺序   
  326.     (*conn)->is_bigendian = _rpc_is_bigendian;  
  327.     // 设置主机名   
  328.     if (!host || host[0]==0)  
  329.         strcpy_s((*conn)->host, 128, "localhost");  
  330.     else if (strlen(host)<128)  
  331.         strcpy_s((*conn)->host, 128,  host);  
  332.     else {  
  333.         rpc_connection_free(*conn);  
  334.         return rpc_throw_error(RPC_USER_ERROR, RPC_HOSTNAME_TOOLONG, "rpc_connection_create()", err);  
  335.     }  
  336.       
  337.     // 设置端口号:   
  338.     // 必须是 gde:xxxx   
  339.     if (!port || port[0]==0 || strlen(port)<4 || strlen(port)>5) {  
  340.         rpc_connection_free(*conn);  
  341.         return rpc_throw_error(RPC_USER_ERROR, RPC_INVALID_PORT, "rpc_connection_create()", err);  
  342.     }  
  343.     i = 0;  
  344.     while( port[i] != 0 ){  
  345.         if ( !isdigit(port[i]) ){  
  346.             rpc_connection_free(*conn);  
  347.             return rpc_throw_error(RPC_USER_ERROR, RPC_INVALID_PORT, "rpc_connection_create()", err);         
  348.         }  
  349.         i++;  
  350.     }  
  351.     i = atoi(port);  
  352.     if (i<0x0400 || i>0xFFFF) { // port = [1024,65535]   
  353.         rpc_connection_free(*conn);  
  354.         return rpc_throw_error(RPC_USER_ERROR, RPC_PORTNUM_OUTOF_SCOPE, "rpc_connection_create()", err);  
  355.     }  
  356.     strcpy_s((*conn)->port, 6, port);  
  357.           
  358.     // 打开SOCKET   
  359.     if (RPC_SUCCESS != opensocket(&((*conn)->stream), host, i, err)){  
  360.         rpc_connection_free(*conn);  
  361.         return RPC_ERROR;  
  362.     }  
  363.     /* 
  364.      * set timeout for recv */  
  365.     if (rcvtimeo >= 0){  
  366.         tv_out.tv_sec  = rcvtimeo/1000;  
  367.         tv_out.tv_usec = (rcvtimeo%1000)*1000;  
  368.         i = setsockopt((*conn)->stream, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv_out, sizeof(tv_out));  
  369.         assert(i == 0);  
  370.     }  
  371.     (*conn)->timeout = rcvtimeo;  
  372.     return RPC_SUCCESS;  
  373. }  
  374. void rpc_connection_free(rpc_connection_descriptor *conn)  
  375. {  
  376.     if (conn){  
  377.         closesocket(conn->stream);  
  378.         WSACleanup();  
  379.         FREE_S(conn)  
  380.     }  
  381. }  
  382. void rpc_connection_set(rpc_connection_descriptor *conn, dword_t token, dword_t timeout, byte enc_hdr, byte enc_pkg)  
  383. {  
  384.     conn->token = token;  
  385.     conn->timeout = timeout;  
  386.     conn->enc_hdr = enc_hdr;  
  387.     conn->enc_pkg = enc_pkg;  
  388. }  
  389. // 计算参数字节总数   
  390. dword_t rpc_param_get_size(rpc_param_descriptor *param)  
  391. {  
  392.     return RPC_PARAM_HEADER_SIZE + (dword_t)param->param_size;  
  393. }  
  394. // 计算调用消息的字节总数   
  395. dword_t rpc_invoke_get_size(rpc_invoke_descriptor *inv)  
  396. {  
  397.     ushort   i;  
  398.     dword_t  cbTotal = RPC_INVOKE_HEADER_SIZE;  
  399.       
  400.     // 列集头24字节:   
  401.     //   ['RCmn'(4)|用户标识(4)|总消息字节(4)|标志(2)| 保留(2)|返回值(4)|方法序号(2)|参数数目(2)]   
  402.     // 计算列集参数字节   
  403.     for (i=0; i<inv->num_params; i++)  
  404.         cbTotal += rpc_param_get_size(&(inv->params_list[i]));  
  405.       
  406.     return cbTotal;  
  407. }  
  408. // 把当前调用的数据全部放到totalBuf中, 返回全部字节数   
  409. /*  24字节头 + 内容 
  410.  *  ['RCmn'(4)|用户token(4)|总消息字节(4)|标志(2)| 保留(2)|返回值(4)|方法序号(2)|参数数目(2)] 
  411.  */  
  412. int rpc_invoke_marshal(rpc_invoke_descriptor *inv, char *totalBuf, int totalSize)  
  413. {  
  414.     word_t   w;  
  415.     dword_t  dw;  
  416.     dword_t  pos;  
  417.     char     key[33];  
  418.     SET_BIT(inv->bitsFlag, RPC_BIGENDIAN_BIT, inv->bigEndian);  
  419.     SET_BIT(inv->bitsFlag, RPC_ENCHEADER_BIT, inv->encHdr==0? 0:1);  
  420.     SET_BIT(inv->bitsFlag, RPC_ENCPACKAGE_BIT, inv->encPkg==0? 0:1);  
  421.     // 列集方法头   
  422.     totalBuf[0] = 'R';  
  423.     totalBuf[1] = 'C';  
  424.     totalBuf[2] = inv->encPkg;  
  425.     totalBuf[3] = inv->encHdr;  
  426.     pos = 4;  
  427.     dw = dword_hton(inv->invToken);  
  428.     memcpy(totalBuf+pos, &dw, 4);  
  429.     pos += 4;  
  430.     dw = dword_hton(totalSize);  
  431.     memcpy(totalBuf+pos, &dw, 4);  
  432.     pos += 4;  
  433.           
  434.     w = word_hton(inv->bitsFlag);  
  435.     memcpy(totalBuf+pos, &w, 2);  
  436.     pos += 2;  
  437.     w = 0;  
  438.     memcpy(totalBuf+pos, &w, 2);  
  439.     pos += 2;  
  440.     dw = dword_hton(inv->result);  
  441.     memcpy(totalBuf+pos, &dw, 4);  
  442.     pos += 4;  
  443.     w = word_hton(inv->ordinal);  
  444.     memcpy(totalBuf+pos, &w, 2);  
  445.     pos += 2;  
  446.     w = word_hton(inv->num_params);  
  447.     memcpy(totalBuf+pos, &w, 2);  
  448.     pos += 2;  
  449.     assert(pos==RPC_INVOKE_HEADER_SIZE);  
  450.           
  451.     // 列集每个参数   
  452.     for (w=0; w<inv->num_params; w++){  
  453.         assert((int)pos<=totalSize);  
  454.         pos += rpc_param_marshal(&inv->params_list[w], totalBuf+pos);          
  455.     }  
  456.     // 加密包数据   
  457.     if (inv->encPkg != 0){  
  458.         dword_t dw = inv->encPkg;  
  459.         srand(dw);  
  460.         MD5_hash_string(totalBuf, RPC_INVOKE_HEADER_SIZE, (dw<<24)+rand(), key);  
  461.         RC4_encrypt_string(totalBuf+RPC_INVOKE_HEADER_SIZE, totalSize-RPC_INVOKE_HEADER_SIZE, key+8, 16);  
  462.     }  
  463.     // 加密消息头   
  464.     if (inv->encHdr != 0){  
  465.         dw = inv->encHdr;  
  466.         srand(dw);  
  467.         MD5_hash_string(totalBuf, 8, (dw<<16)+rand(), key);  
  468.         RC4_encrypt_string(totalBuf+4, RPC_INVOKE_HEADER_SIZE-4, key, 16);  
  469.     }  
  470.     return pos;   
  471. }  
  472. /**  
  473.  * 散集调用头  
  474.  */  
  475. RPCRESULT rpc_invokehdr_unmarshal(SOCKET sClient, dword_t dwToken, char *rpcHdr, int hdrSize, rpc_invoke_descriptor *inv, rpc_invoke_error *err)  
  476. {  
  477.     /** 
  478.      * Perform a blocking recv() call 
  479.      *  ['RCmn'(4)|用户标识(4)|总消息字节(4)|标志(2)| 保留(2)|返回值(4)|方法序号(2)|参数数目(2)] */  
  480.     assert(hdrSize == RPC_INVOKE_HEADER_SIZE);  
  481.     if (RPC_INVOKE_HEADER_SIZE != recvmsg(sClient, rpcHdr, RPC_INVOKE_HEADER_SIZE, 0))  
  482.         return rpc_throw_error(RPC_USER_ERROR, RPC_INVALIDMSG, "RecvRpcCallHeader", err);  
  483.               
  484.     // 读调用声明 = "RPCn", n为0-255的密钥种子. 0表示不加密; !=0表示RC4加密的密钥种子   
  485.     if (rpcHdr[0]!='R'||rpcHdr[1]!='C')  
  486.         return rpc_throw_error(RPC_USER_ERROR, RPC_INVALIDMSG, "RecvRpcCallHeader", err);  
  487.     inv->encPkg = rpcHdr[2];  
  488.     inv->encHdr = rpcHdr[3];  
  489.     if (inv->encHdr != 0){  
  490.         dword_t dw;  
  491.         char    hdr[41];  
  492.         hdr[0]=rpcHdr[0];  
  493.         hdr[1]=rpcHdr[1];  
  494.         hdr[2]=rpcHdr[2];  
  495.         hdr[3]=rpcHdr[3];  
  496.           
  497.         dw = dword_hton(dwToken);  
  498.         memcpy(&hdr[4], &dw, 4);  
  499.         dw=inv->encHdr;  
  500.         srand(dw);  
  501.         MD5_hash_string(hdr, 8, (dw<<16)+rand(), hdr+8);  
  502.         RC4_encrypt_string(rpcHdr+4, RPC_INVOKE_HEADER_SIZE-4, hdr+8, 16);  
  503.     }  
  504.       
  505.     inv->invToken = dword_ntoh(*((dword_t*)(rpcHdr+4)));         // 用户标识    
  506.     inv->totalBytes = dword_ntoh(*((dword_t*)(rpcHdr+8)));           // 总消息字节数(也许是压缩的)   
  507.     inv->bitsFlag = word_ntoh(*((word_t*)(rpcHdr+12)));              // 标志      
  508.     inv->bigEndian = GET_BIT(inv->bitsFlag, RPC_BIGENDIAN_BIT);       // 客户方列集的字节次序   
  509.     inv->reserved = word_ntoh(*((word_t*)(rpcHdr+14)));              // 保留值   
  510.     inv->result = dword_ntoh(*((dword_t*)(rpcHdr+16)));              // 返回值   
  511.     inv->ordinal = word_ntoh(*((word_t*)(rpcHdr+20)));               // 方法序号   
  512.     inv->num_params = word_ntoh(*((word_t*)(rpcHdr+22)));            // 参数数目   
  513.               
  514.     return RPC_SUCCESS;  
  515. }  
  516. /* 散集数据到参数中, 数据头总是不压缩的. 参数数据总是先压缩后加密的 
  517.  * 24字节头 + 内容 
  518.  *  ['RCmn'(4)|用户标识(4)|总消息字节(4)|标志(2)| 保留(2)|返回值(4)|方法序号(2)|参数数目(2)]  
  519.  */  
  520. RPCRESULT rpc_invoke_unmarshal(rpc_invoke_descriptor *inv,   
  521.                                char *totalBuf,   
  522.                                size_t totalSize,  
  523.                                rpc_param_descriptor **out_params,  
  524.                                word_t *num_params,  
  525.                                rpc_invoke_error *err)  
  526. {  
  527.     ushort    i;  
  528.     size_t    pos;  
  529.     rpc_param_descriptor *params_list;  
  530.     assert(totalSize >= RPC_INVOKE_HEADER_SIZE);  
  531.                   
  532.     // 读调用声明 = "RCmn", m,n为0-255的密钥种子. 0表示不加密; !=0表示RC4加密的密钥种子   
  533.     assert(totalBuf[0]=='R'&&totalBuf[1]=='C');  
  534.     // 解密包数据   
  535.     if (inv->encPkg != 0){  
  536.         char    key[33];  
  537.         dword_t dw = inv->encPkg;  
  538.         srand(dw);  
  539.         MD5_hash_string(totalBuf, RPC_INVOKE_HEADER_SIZE, (dw<<24)+rand(), key);  
  540.         RC4_encrypt_string(totalBuf+RPC_INVOKE_HEADER_SIZE, totalSize-RPC_INVOKE_HEADER_SIZE, key+8, 16);  
  541.     }  
  542.           
  543.     pos = RPC_INVOKE_HEADER_SIZE;  
  544.     // 分配参数数组   
  545.     MALLOC_S(params_list, inv->num_params, rpc_param_descriptor)  
  546.     for (i=0; i<inv->num_params; i++){  
  547.         pos += rpc_param_unmarshal(inv->bigEndian, &params_list[i], totalBuf+pos);  
  548.     }     
  549.     *out_params = params_list;  
  550.     *num_params = inv->num_params;  
  551.     assert(pos == totalSize);     
  552.     return RPC_SUCCESS;  
  553. }  
  554. RPCRESULT rpc_invoke_execute(rpc_connection_descriptor *conn, rpc_invoke_descriptor *inv, rpc_invoke_descriptor *outv, rpc_invoke_error* err)  
  555. {  
  556.     inv->encHdr    = conn->enc_hdr;  
  557.     inv->encPkg    = conn->enc_pkg;     
  558.     inv->invToken  = conn->token;  
  559.     inv->bigEndian = conn->is_bigendian? 1:0;  
  560.     if (RPC_SUCCESS != rpc_invoke_send(conn, inv, err)){  
  561.         assert(0);  
  562.         return err->err_code;  
  563.     }  
  564.     if (RPC_SUCCESS != rpc_invoke_recv(conn, outv, err))  
  565.         return err->err_code;  
  566.     return RPC_SUCCESS;  
  567. }  
/** * rpcapi.c -cheungmine@gmail.com */ #include "rpcapi.h" // 打开socket static RPCRESULT opensocket(SOCKET *pStream, const char *lpszServer, int nPort, rpc_invoke_error *pError) { struct sockaddr_in server; struct hostent *hp = 0; unsigned int iAddr; *pStream = INVALID_SOCKET; // Parse server host if(inet_addr(lpszServer) == INADDR_NONE){ hp = gethostbyname(lpszServer); if(hp==0) return rpc_throw_error(RPC_USER_ERROR, RPC_INVALID_HOST, "opensocket()", pError); server.sin_addr.s_addr = *((unsigned long*)hp->h_addr); } else{ iAddr = inet_addr(lpszServer); server.sin_addr.s_addr = iAddr; // too slow to use gethostbyaddr //OLD: hp = gethostbyaddr((char*)&iAddr, sizeof(iAddr), AF_INET); //OLD: if(hp==0) //OLD: return rpc_throw_error(RPC_USER_ERROR, RPC_INVALID_HOST, "opensocket()", pError); //OLD: server.sin_addr.s_addr = *((unsigned long*)hp->h_addr); } server.sin_family = AF_INET; server.sin_port = htons((u_short)nPort); // Create a new socket and attempt to connect to server (*pStream) = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if ((*pStream) == INVALID_SOCKET) return rpc_throw_error(RPC_SOCKET_ERROR, WSAGetLastError(), "socket()", pError); // Make a connection to the server if (connect((*pStream), (struct sockaddr *) &server, sizeof(server))==SOCKET_ERROR){ closesocket( *pStream ); *pStream = INVALID_SOCKET; return rpc_throw_error(RPC_SOCKET_ERROR, WSAGetLastError(), "connect()", pError); } setbufsize(*pStream, RPC_BUFFSIZE, RPC_BUFFSIZE); return RPC_SUCCESS; } // 列集参数 static int rpc_param_marshal(rpc_param_descriptor *param, char *buf) { word_t w; dword_t dw; int pos = 0; // 参数头RPC_PARAM_HEADER_SIZE字节: // [参数类型(2)|类型字节(2)|数组元素数目(4)|参数数据字节数(4)|参数成员数(2)=0|保留(2)=0] w = word_hton(param->param_type); memcpy(buf+pos, &w, 2); pos += 2; w = word_hton(param->size_type); memcpy(buf+pos, &w, 2); pos += 2; dw = dword_hton((dword_t)param->array_size); memcpy(buf+pos, &dw, 4); pos += 4; dw = dword_hton((dword_t)param->param_size); memcpy(buf+pos, &dw, 4); pos += 4; w = 0; memcpy(buf+pos, &w, 2); pos += 2; w = 0; memcpy(buf+pos, &w, 2); pos += 2; // 参数的数据 memcpy(buf+pos, param->param_bytes, param->param_size); pos += (int)param->param_size; return pos; } // 散集参数 // 参数头RPC_PARAM_HEADER_SIZE字节: // [参数类型(2)|类型字节(2)|数组元素数目(4)|参数数据字节数(4)|参数成员数(2)|保留(2)=0] static size_t rpc_param_unmarshal(BOOL marshal_bigendian, rpc_param_descriptor *param, char *buf) { byte *pcb; size_t i; size_t pos = 0; assert(param->array_size==0||param->array_size==param->param_size/param->size_type); // 参数类型 param->param_type = word_ntoh(*((word_t*)(buf+pos))); pos += 2; param->size_type = word_ntoh(*((word_t*)(buf+pos))); pos += 2; param->array_size = dword_ntoh(*((dword_t*)(buf+pos))); pos += 4; param->param_size = dword_ntoh(*((dword_t*)(buf+pos))); pos += 4; // 参数成员 pos += 2; // 保留值 pos += 2; // 参数字节指针 // 这里假设列集方marshal_bigendian和散集方_rpc_is_bigendian的字节次序一致, // 以后要添加代码处理不一致的情况 if (param->param_size==0){ param->param_bytes = 0; return pos; } if (param->size_type==1 || marshal_bigendian==_rpc_is_bigendian){ param->param_bytes = (void*)(buf+pos); return (pos + param->param_size); } // 必须交换字节次序 // assert(param->size_type==2||param->size_type==4||param->size_type==8); assert(marshal_bigendian != _rpc_is_bigendian); param->param_bytes = (void*)(buf+pos); pcb = (buf+pos); i = param->param_size/param->size_type; while(i-->0){ swap_bytes(&pcb[i*param->size_type], param->size_type); } assert(i==-1); return (pos + param->param_size); } void rpc_param_get_ushort (rpc_param_descriptor *param, USHORT *val) { assert(param && param->param_bytes && param->array_size==0 && param->param_type==RPCT_USHORT && param->size_type==RPC_TYPE_SIZE(RPCT_USHORT)); *val = *((USHORT*)(param->param_bytes)); } void rpc_param_get_short (rpc_param_descriptor *param, SHORT *val) { assert(param && param->param_bytes && param->array_size==0 && param->param_type==RPCT_SHORT && param->size_type==RPC_TYPE_SIZE(RPCT_SHORT)); *val = *((SHORT*)(param->param_bytes)); } void rpc_param_get_long (rpc_param_descriptor *param, LONG *val) { assert(param && param->param_bytes && param->array_size==0 && param->param_type==RPCT_LONG && param->size_type==RPC_TYPE_SIZE(RPCT_LONG)); *val = *((LONG*)(param->param_bytes)); } void rpc_param_get_int (rpc_param_descriptor *param, INT *val) { assert(param && param->param_bytes && param->array_size==0 && param->param_type==RPCT_INT && param->size_type==RPC_TYPE_SIZE(RPCT_INT)); *val = *((INT*)(param->param_bytes)); } void rpc_param_get_ulong (rpc_param_descriptor *param, ULONG *val) { assert(param && param->param_bytes && param->array_size==0 && param->param_type==RPCT_ULONG && param->size_type==RPC_TYPE_SIZE(RPCT_ULONG)); *val = *((ULONG*)(param->param_bytes)); } void rpc_param_get_double (rpc_param_descriptor *param, DOUBLE *val) { assert(param && param->param_bytes && param->array_size==0 && param->param_type==RPCT_DOUBLE && param->size_type==RPC_TYPE_SIZE(RPCT_DOUBLE)); *val = *((DOUBLE*)(param->param_bytes)); } RPCRESULT rpc_invoke_send(rpc_connection_descriptor *conn, rpc_invoke_descriptor *inv, rpc_invoke_error *err) { BOOL br; char *buffer = 0; dword_t cbTotal = 0; cbTotal = rpc_invoke_get_size(inv); // 既然<=RPC_BUFFSIZE, 则使用默认的buffer if (cbTotal <= RPC_BUFFSIZE){ cbTotal = rpc_invoke_marshal(inv, conn->buffer, cbTotal); assert(cbTotal != -1); if (cbTotal != sendmsg(conn->stream, conn->buffer, cbTotal, 0)) return rpc_throw_error(RPC_SOCKET_ERROR, WSAGetLastError(), "rpc_invoke_send()", err); else return RPC_SUCCESS; } else { buffer = malloc(cbTotal); // 内存分配失败 if (!buffer) return rpc_throw_error(RPC_SYSTEM_ERROR, GetLastError(), "rpc_invoke_send()", err); cbTotal = rpc_invoke_marshal(inv, buffer, cbTotal); assert(cbTotal != -1); // 发送大块数据 br = sendbulk(conn->stream, buffer, cbTotal, 0, RPC_BUFFSIZE); FREE_S(buffer) if (!br) return rpc_throw_error(RPC_SOCKET_ERROR, WSAGetLastError(), "rpc_invoke_send()", err); else return RPC_SUCCESS; } } RPCRESULT rpc_invoke_recv(rpc_connection_descriptor *conn, rpc_invoke_descriptor *outv, rpc_invoke_error *err) { RPCRESULT res; // 接收头 res = rpc_invokehdr_unmarshal(conn->stream, conn->token, conn->buffer, RPC_INVOKE_HEADER_SIZE, outv, err); if (RPC_SUCCESS != res) return res; // 验证token if (conn->token != outv->invToken) return rpc_throw_error(RPC_USER_ERROR, RPC_INVALIDMSG, "rpc_invoke_recv()", err); // 接收其余全部数据 if (outv->totalBytes > RPC_BUFFSIZE){ MALLOC_S(outv->pbBuf, outv->totalBytes, char); memcpy(outv->pbBuf, conn->buffer, RPC_INVOKE_HEADER_SIZE); } else{ outv->pbBuf = conn->buffer; } assert(outv->pbBuf); if (!recvbulk(conn->stream, outv->pbBuf+RPC_INVOKE_HEADER_SIZE, outv->totalBytes-RPC_INVOKE_HEADER_SIZE, 0, RPC_BUFFSIZE)){ if (outv->pbBuf != conn->buffer){ FREE_S(outv->pbBuf) outv->pbBuf = 0; } return rpc_throw_error(RPC_USER_ERROR, RPC_NETWORK_ERROR, "rpc_invoke_recv()", err); } if (RPC_SUCCESS != rpc_invoke_unmarshal(outv, outv->pbBuf, outv->totalBytes, &outv->params_list, &outv->num_params, err)){ if (outv->pbBuf != conn->buffer){ FREE_S(outv->pbBuf) outv->pbBuf = 0; } return rpc_throw_error(RPC_USER_ERROR, RPC_INVALIDMSG, "rpc_invoke_recv()", err); } return RPC_SUCCESS; } /*============================================================================= Public Functions Remote Procedure Call Impementation =============================================================================*/ rpc_invoke_descriptor* rpc_invoke_create(rpc_invoke_descriptor **inv, ushort ordinal, ushort num_params) { assert(inv); MALLOC_S(*inv, 1, rpc_invoke_descriptor) assert(*inv); (*inv)->bigEndian = _rpc_is_bigendian; (*inv)->ordinal = ordinal; (*inv)->num_params = num_params; MALLOC_S((*inv)->params_list, num_params, rpc_param_descriptor) return (*inv); } rpc_invoke_descriptor * rpc_invoke_init(rpc_invoke_descriptor *inv, ushort ordinal, ushort num_params) { assert(inv); rpc_invoke_clear_all(inv); inv->ordinal = ordinal; inv->num_params = num_params; MALLOC_S(inv->params_list, num_params, rpc_param_descriptor) return inv; } void rpc_invoke_clear_all(rpc_invoke_descriptor *inv) { assert(inv); if (inv->pbBuf && inv->totalBytes>RPC_BUFFSIZE){ FREE_S(inv->pbBuf) assert(inv->pbBuf==0); } rpc_param_free_list(inv->params_list, inv->num_params); memset(inv, 0, sizeof(rpc_invoke_descriptor)); inv->bigEndian = _rpc_is_bigendian? 1:0; } void rpc_invoke_free(rpc_invoke_descriptor *inv) { rpc_invoke_clear_all(inv); FREE_S(inv) } rpc_param_descriptor* rpc_invoke_bind_param(rpc_invoke_descriptor *inv, ushort id, word_t type, void *vaddr, size_t array_size, BOOL is_owner) { rpc_param_descriptor* p; assert(id>=0 && id<inv->num_params); p = &inv->params_list[id]; p->param_type = type; p->size_type = RPC_TYPE_SIZE(type); p->array_size = array_size; p->param_bytes = vaddr; // may be NULL if (type == RPCT_STRING) p->param_size = array_size; else p->param_size = p->size_type * (array_size > 0? array_size : 1); p->is_owner = is_owner; return p; } void rpc_param_clear(rpc_param_descriptor *p) { if (p->is_owner) FREE_S(p->param_bytes) memset(p, 0, sizeof(rpc_param_descriptor)); } void rpc_param_free_list(rpc_param_descriptor *param_list, word_t num_params) { while(num_params-->0) rpc_param_clear(&param_list[num_params]); FREE_S(param_list) } RPCRESULT rpc_connection_create(rpc_connection_descriptor **conn, const char *host, const char *port, long rcvtimeo, rpc_invoke_error *err) { WSADATA wsd; struct timeval tv_out; int i; // 加载WinSock DLL if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0) return rpc_throw_error(RPC_USER_ERROR, RPC_WINSOCK_NOTFOUND, "WSAStartup()", err); // 创建对象 MALLOC_S(*conn, 1, rpc_connection_descriptor) // 设置字节顺序 (*conn)->is_bigendian = _rpc_is_bigendian; // 设置主机名 if (!host || host[0]==0) strcpy_s((*conn)->host, 128, "localhost"); else if (strlen(host)<128) strcpy_s((*conn)->host, 128, host); else { rpc_connection_free(*conn); return rpc_throw_error(RPC_USER_ERROR, RPC_HOSTNAME_TOOLONG, "rpc_connection_create()", err); } // 设置端口号: // 必须是 gde:xxxx if (!port || port[0]==0 || strlen(port)<4 || strlen(port)>5) { rpc_connection_free(*conn); return rpc_throw_error(RPC_USER_ERROR, RPC_INVALID_PORT, "rpc_connection_create()", err); } i = 0; while( port[i] != 0 ){ if ( !isdigit(port[i]) ){ rpc_connection_free(*conn); return rpc_throw_error(RPC_USER_ERROR, RPC_INVALID_PORT, "rpc_connection_create()", err); } i++; } i = atoi(port); if (i<0x0400 || i>0xFFFF) { // port = [1024,65535] rpc_connection_free(*conn); return rpc_throw_error(RPC_USER_ERROR, RPC_PORTNUM_OUTOF_SCOPE, "rpc_connection_create()", err); } strcpy_s((*conn)->port, 6, port); // 打开SOCKET if (RPC_SUCCESS != opensocket(&((*conn)->stream), host, i, err)){ rpc_connection_free(*conn); return RPC_ERROR; } /* * set timeout for recv */ if (rcvtimeo >= 0){ tv_out.tv_sec = rcvtimeo/1000; tv_out.tv_usec = (rcvtimeo%1000)*1000; i = setsockopt((*conn)->stream, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv_out, sizeof(tv_out)); assert(i == 0); } (*conn)->timeout = rcvtimeo; return RPC_SUCCESS; } void rpc_connection_free(rpc_connection_descriptor *conn) { if (conn){ closesocket(conn->stream); WSACleanup(); FREE_S(conn) } } void rpc_connection_set(rpc_connection_descriptor *conn, dword_t token, dword_t timeout, byte enc_hdr, byte enc_pkg) { conn->token = token; conn->timeout = timeout; conn->enc_hdr = enc_hdr; conn->enc_pkg = enc_pkg; } // 计算参数字节总数 dword_t rpc_param_get_size(rpc_param_descriptor *param) { return RPC_PARAM_HEADER_SIZE + (dword_t)param->param_size; } // 计算调用消息的字节总数 dword_t rpc_invoke_get_size(rpc_invoke_descriptor *inv) { ushort i; dword_t cbTotal = RPC_INVOKE_HEADER_SIZE; // 列集头24字节: // ['RCmn'(4)|用户标识(4)|总消息字节(4)|标志(2)| 保留(2)|返回值(4)|方法序号(2)|参数数目(2)] // 计算列集参数字节 for (i=0; i<inv->num_params; i++) cbTotal += rpc_param_get_size(&(inv->params_list[i])); return cbTotal; } // 把当前调用的数据全部放到totalBuf中, 返回全部字节数 /* 24字节头 + 内容 * ['RCmn'(4)|用户token(4)|总消息字节(4)|标志(2)| 保留(2)|返回值(4)|方法序号(2)|参数数目(2)] */ int rpc_invoke_marshal(rpc_invoke_descriptor *inv, char *totalBuf, int totalSize) { word_t w; dword_t dw; dword_t pos; char key[33]; SET_BIT(inv->bitsFlag, RPC_BIGENDIAN_BIT, inv->bigEndian); SET_BIT(inv->bitsFlag, RPC_ENCHEADER_BIT, inv->encHdr==0? 0:1); SET_BIT(inv->bitsFlag, RPC_ENCPACKAGE_BIT, inv->encPkg==0? 0:1); // 列集方法头 totalBuf[0] = 'R'; totalBuf[1] = 'C'; totalBuf[2] = inv->encPkg; totalBuf[3] = inv->encHdr; pos = 4; dw = dword_hton(inv->invToken); memcpy(totalBuf+pos, &dw, 4); pos += 4; dw = dword_hton(totalSize); memcpy(totalBuf+pos, &dw, 4); pos += 4; w = word_hton(inv->bitsFlag); memcpy(totalBuf+pos, &w, 2); pos += 2; w = 0; memcpy(totalBuf+pos, &w, 2); pos += 2; dw = dword_hton(inv->result); memcpy(totalBuf+pos, &dw, 4); pos += 4; w = word_hton(inv->ordinal); memcpy(totalBuf+pos, &w, 2); pos += 2; w = word_hton(inv->num_params); memcpy(totalBuf+pos, &w, 2); pos += 2; assert(pos==RPC_INVOKE_HEADER_SIZE); // 列集每个参数 for (w=0; w<inv->num_params; w++){ assert((int)pos<=totalSize); pos += rpc_param_marshal(&inv->params_list[w], totalBuf+pos); } // 加密包数据 if (inv->encPkg != 0){ dword_t dw = inv->encPkg; srand(dw); MD5_hash_string(totalBuf, RPC_INVOKE_HEADER_SIZE, (dw<<24)+rand(), key); RC4_encrypt_string(totalBuf+RPC_INVOKE_HEADER_SIZE, totalSize-RPC_INVOKE_HEADER_SIZE, key+8, 16); } // 加密消息头 if (inv->encHdr != 0){ dw = inv->encHdr; srand(dw); MD5_hash_string(totalBuf, 8, (dw<<16)+rand(), key); RC4_encrypt_string(totalBuf+4, RPC_INVOKE_HEADER_SIZE-4, key, 16); } return pos; } /** * 散集调用头 */ RPCRESULT rpc_invokehdr_unmarshal(SOCKET sClient, dword_t dwToken, char *rpcHdr, int hdrSize, rpc_invoke_descriptor *inv, rpc_invoke_error *err) { /** * Perform a blocking recv() call * ['RCmn'(4)|用户标识(4)|总消息字节(4)|标志(2)| 保留(2)|返回值(4)|方法序号(2)|参数数目(2)] */ assert(hdrSize == RPC_INVOKE_HEADER_SIZE); if (RPC_INVOKE_HEADER_SIZE != recvmsg(sClient, rpcHdr, RPC_INVOKE_HEADER_SIZE, 0)) return rpc_throw_error(RPC_USER_ERROR, RPC_INVALIDMSG, "RecvRpcCallHeader", err); // 读调用声明 = "RPCn", n为0-255的密钥种子. 0表示不加密; !=0表示RC4加密的密钥种子 if (rpcHdr[0]!='R'||rpcHdr[1]!='C') return rpc_throw_error(RPC_USER_ERROR, RPC_INVALIDMSG, "RecvRpcCallHeader", err); inv->encPkg = rpcHdr[2]; inv->encHdr = rpcHdr[3]; if (inv->encHdr != 0){ dword_t dw; char hdr[41]; hdr[0]=rpcHdr[0]; hdr[1]=rpcHdr[1]; hdr[2]=rpcHdr[2]; hdr[3]=rpcHdr[3]; dw = dword_hton(dwToken); memcpy(&hdr[4], &dw, 4); dw=inv->encHdr; srand(dw); MD5_hash_string(hdr, 8, (dw<<16)+rand(), hdr+8); RC4_encrypt_string(rpcHdr+4, RPC_INVOKE_HEADER_SIZE-4, hdr+8, 16); } inv->invToken = dword_ntoh(*((dword_t*)(rpcHdr+4))); // 用户标识 inv->totalBytes = dword_ntoh(*((dword_t*)(rpcHdr+8))); // 总消息字节数(也许是压缩的) inv->bitsFlag = word_ntoh(*((word_t*)(rpcHdr+12))); // 标志 inv->bigEndian = GET_BIT(inv->bitsFlag, RPC_BIGENDIAN_BIT); // 客户方列集的字节次序 inv->reserved = word_ntoh(*((word_t*)(rpcHdr+14))); // 保留值 inv->result = dword_ntoh(*((dword_t*)(rpcHdr+16))); // 返回值 inv->ordinal = word_ntoh(*((word_t*)(rpcHdr+20))); // 方法序号 inv->num_params = word_ntoh(*((word_t*)(rpcHdr+22))); // 参数数目 return RPC_SUCCESS; } /* 散集数据到参数中, 数据头总是不压缩的. 参数数据总是先压缩后加密的 * 24字节头 + 内容 * ['RCmn'(4)|用户标识(4)|总消息字节(4)|标志(2)| 保留(2)|返回值(4)|方法序号(2)|参数数目(2)] */ RPCRESULT rpc_invoke_unmarshal(rpc_invoke_descriptor *inv, char *totalBuf, size_t totalSize, rpc_param_descriptor **out_params, word_t *num_params, rpc_invoke_error *err) { ushort i; size_t pos; rpc_param_descriptor *params_list; assert(totalSize >= RPC_INVOKE_HEADER_SIZE); // 读调用声明 = "RCmn", m,n为0-255的密钥种子. 0表示不加密; !=0表示RC4加密的密钥种子 assert(totalBuf[0]=='R'&&totalBuf[1]=='C'); // 解密包数据 if (inv->encPkg != 0){ char key[33]; dword_t dw = inv->encPkg; srand(dw); MD5_hash_string(totalBuf, RPC_INVOKE_HEADER_SIZE, (dw<<24)+rand(), key); RC4_encrypt_string(totalBuf+RPC_INVOKE_HEADER_SIZE, totalSize-RPC_INVOKE_HEADER_SIZE, key+8, 16); } pos = RPC_INVOKE_HEADER_SIZE; // 分配参数数组 MALLOC_S(params_list, inv->num_params, rpc_param_descriptor) for (i=0; i<inv->num_params; i++){ pos += rpc_param_unmarshal(inv->bigEndian, &params_list[i], totalBuf+pos); } *out_params = params_list; *num_params = inv->num_params; assert(pos == totalSize); return RPC_SUCCESS; } RPCRESULT rpc_invoke_execute(rpc_connection_descriptor *conn, rpc_invoke_descriptor *inv, rpc_invoke_descriptor *outv, rpc_invoke_error* err) { inv->encHdr = conn->enc_hdr; inv->encPkg = conn->enc_pkg; inv->invToken = conn->token; inv->bigEndian = conn->is_bigendian? 1:0; if (RPC_SUCCESS != rpc_invoke_send(conn, inv, err)){ assert(0); return err->err_code; } if (RPC_SUCCESS != rpc_invoke_recv(conn, outv, err)) return err->err_code; return RPC_SUCCESS; }

 

 

整个工程的代码随后上传:

 

http://cheungmine.download.csdn.net/

 

 

from:http://blog.csdn.net/ubuntu64fan/article/details/5660975

目录
相关文章
|
7月前
|
C++
有趣的动态转换
有趣的动态转换
|
C# C++
创建目标类型对象在C#7.3中不可用,请使用9.0或更高的语言版本
创建目标类型对象在C#7.3中不可用,请使用9.0或更高的语言版本
1103 0
创建目标类型对象在C#7.3中不可用,请使用9.0或更高的语言版本
|
1月前
|
编译器 C++
47不同类型数据间的转换
47不同类型数据间的转换
5 0
|
5月前
ECharts分段型视觉映射组件的属性修改
ECharts分段型视觉映射组件的属性修改
32 0
|
7月前
|
安全
RxSwift特征序列Driver的使用,以及共享附加作用与非共享附加作用的区别?
RxSwift特征序列Driver的使用,以及共享附加作用与非共享附加作用的区别?
131 0
|
10月前
|
数据采集 移动开发 数据可视化
空间转录组|Load10X_Spatial函数修改适配多形式数据 + 空转标准流程
空间转录组|Load10X_Spatial函数修改适配多形式数据 + 空转标准流程
363 0
|
存储 程序员 C语言
如何进行C++动态转换
如何进行C++动态转换
如何进行C++动态转换
|
JavaScript 前端开发 算法
从规范的角度解析对象 — 原始值转换
从规范的角度解析对象 — 原始值转换
103 0
从规范的角度解析对象 — 原始值转换
|
存储 SQL 编解码
base64编码底层转换规则举例解读
base64编码底层转换规则举例解读
202 0
base64编码底层转换规则举例解读