将用户自定义的C结构数据存储成VARIANT类型,需要时再将VARIANT类型转为用户自定义的结构数据,有十分现实的意义,既然我们不想为这样的结构数据写一个COM包装类。虽然有很多方法和手段生成这样的VARIANT,但是,多数时候可能需要一个更加简单的,灵活的方法。我在做远程过程调用的C接口时,忽然联想到,既然RPC可以把任何数据以字节的形式发送,那么,就可以利用这个机制,把结构打包成字节数组。而字节数据是可以很方便地存储在VARIANT中。
这个过程是广为人知的,但是,真正把结构列集成字节数组,如果不想使用某些标称的序列化的方法,而全部自己写,的确要费一番功夫。不是
技术有多难,是很繁琐。我把前2年写的代码翻出来,简单调用一下,就有了这篇文章。采用我的方法,C/C++程序员可以把自己定义的结构放到VARIANT、CComVariant、COleVariant等各种VARIANT中,也可以反向转换。而VARIANT是可以很方便地在COM接口中传递。这样,就多了一种在自动化COM接口中传递自定义结构的手段。
不多说废话,全部内容见下面的代码,我还会上传整个工程。
struct2variant.cpp 如下:
- ///////////////////////////////////////////////////////////////////////
- // 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可以参考如下:
- /**
- * 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如下:
- /**
- * 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(¶m_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, ¶ms_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