ActiveSync應用層程式協議分析-RAPI的握手過程 - 李先靜的專欄 - CSDNBlog

chief1985發表於2008-10-22
導讀:


ActiveSync應用層程式協議分析-RAPI的握手過程


<?XML:NAMESPACE PREFIX = O />

 


轉載時請註明出處和作者聯絡方式
作者聯絡方式:李先靜


 


ActiveSyncWindow Mobile之間的通訊協議並不複雜,在RNDIS+USBNET之上執行TCP/IP,而TCP/IP之上的應用層協議包括RAPIRRAC兩個協議。前段時間我完成RAPIRRAC協議的PC端和裝置端的實現,在這個系列之中,我們將對它們的原理和實現進行分析,供要做類似工作的朋友參考。本文介紹一下RAPI的握手過程。


 


PC端的ActiveSync監聽990埠,同步時裝置連線到這個埠,然後開始握手:


 


1.裝置端傳送四個位元組的資料(0x00)表示請求握手。


2.PC端迴應四個位元組的資料(0x03)表示接受握手,並要求裝置提供裝置資訊。


3.裝置迴應四個位元組的資料(0x04)表示要上傳裝置資訊,並在其後緊跟裝置資訊。


4.PC端讀取裝置資訊,如果不要求論證,握手到此結束(要求握手的情況目前還不清楚)


 


裝置資訊結構如下:


 


       typedef struct _RapiDeviceInfo


       {


              RapiDeviceGuid   guid;


              unsigned int os_version_major;


              unsigned int os_version_minor;


              WStr*  name;


              unsigned int dev_version;


              unsigned int cpu_type;


              unsigned int dev_magic;


              unsigned int current_partner;


              unsigned int dev_id;


              char*  platform;


              char*  model;


              unsigned int components_nr;


              RapiComponent* components;


              unsigned int pw_key;


       }RapiDeviceInfo;


 


這個資料包前面四個位元組是這個結構的資料長度,後面的資料並不是直接按結構記憶體佈局對映過來的,而是有專門編碼方式。主要特殊之外在於,所有整數都是以小端格式存放,name之前有四個位元組代表name的字元數(不包括空字元), platform之前有四個位元組代表platform的位元組數(此時包括空字元)model之前有四個位元組代表model的位元組數(此時不包括空字數)。由這個結構可以看出微軟當時把這個協議定義得太爛了:name是寬字元,而platformmodel是多位元組字串,和前面的name不統一不說,還無法知道它們的編碼方式,更爛的是platformmodel前面長度的意義不一致。


 


PC端的程式碼類似於:


static AsmRet rapi_host_connection_device_handle_hand_shake(AsmConnection* thiz)


{


       AsmRet ret = ASM_RET_FAIL;


       asm_return_val_if_fail(thiz != NULL, ASM_RET_FAIL);


       PrivInfo* priv = (PrivInfo*)thiz->priv;


       asm_return_val_if_fail(priv->stream != NULL, ASM_RET_OK);


 


       int length = 0;


       unsigned int cmd = 0;


       unsigned int resp = 0;


       AsmInputBuffer* input = NULL;


       do


       {


              ret = asm_stream_read(priv->stream, &cmd, sizeof(cmd), &length);


              if(ret != ASM_RET_OK || cmd != RAPI_COMMAND_HAND_SHAKE) break;


 


              resp = RAPI_RESP_HAND_SHAKE;


              ret = asm_stream_write(priv->stream, &resp, sizeof(resp), &length);


              if(ret != ASM_RET_OK) break;


      


              ret = asm_stream_read(priv->stream, &cmd, sizeof(cmd), &length);


              if(ret != ASM_RET_OK || cmd != RAPI_RESP_GET_INFO) break;


             


              input = asm_input_buffer_create(NULL, 0, ASM_ENDIAN_LITTLE, NULL);


              ret = rapi_stream_read(priv->stream, input);


              if(ret != ASM_RET_OK) break;


              ret = rapi_host_connection_device_parse_device_info(thiz, input);


       }while(0);


      


       if(ret != ASM_RET_OK)


       {


              asm_stream_destroy(priv->stream);


              priv->stream = NULL;


              printf("%s:%d hand shake failed./n", __func__, __LINE__);


       }


       asm_input_buffer_destroy(input);


 


       return ASM_RET_OK;


}


 


裝置端的程式碼類似於:


static AsmRet rapi_device_connection_device_hand_shake(AsmConnection* thiz)


{


       AsmRet ret = ASM_RET_FAIL;


       asm_return_val_if_fail(thiz != NULL, ret);


 


       PrivInfo* priv = (PrivInfo*)thiz->priv;


       RapiDeviceInfo info = {0};


       size_t length = 0;


       unsigned int cmd = 0;


       unsigned int resp = 0;


 


       asm_output_buffer_reset(priv->output);


       cmd = uint32_to_endian(RAPI_COMMAND_HAND_SHAKE, ASM_ENDIAN_LITTLE);


 


       ret = asm_stream_write(priv->stream, &cmd, sizeof(cmd), &length);


       assert(length == sizeof(cmd));


 


       ret = asm_stream_read(priv->stream, &resp, sizeof(resp), &length);


       assert(length == sizeof(resp));


       assert(resp == RAPI_RESP_HAND_SHAKE);


 


       cmd = uint32_to_endian(RAPI_RESP_GET_INFO, ASM_ENDIAN_LITTLE);


       ret = asm_stream_write(priv->stream, &cmd, sizeof(cmd), &length);


       assert(length == sizeof(cmd));


 


       if(rapi_device_get_info(priv->device, &info) == ASM_RET_OK)


       {


              if(rapi_buffer_write_info(priv->output, &info) == ASM_RET_OK)


              {


                     ret = rapi_stream_write(priv->stream, priv->output);


              }


       }


 


       return ret;


}


 


~~end~~

 
本文轉自
http://blog.csdn.net/absurd/archive/2008/03/27/2224066.aspx

相關文章