websocket

道法天然 2015/10/30 19:59:17
SendRequestWebData
SendWinsockDataFromStr
道法天然 2015/10/30 20:00:45
SendWebPackDataFromStr
SendlLoginWebData
. 2015/10/30 20:01:26
吃點東西再加班吧
道法天然 2015/10/30 20:01:52
BuidWebSocketPacket
一會就回去了啊
ProcWebSocketKeyValue
SendRequestWebData
道法天然 2015/10/30 20:05:23
SendWebPackDataFromStr
道法天然 2015/10/31 8:10:56
大智者必謙和,大善者必寬容。惟有小智者才咄咄逼人,小善者才斤斤計較。大氣象者,不講排場;講大排場者,露小氣象。大成者謙遜平和,小成者不可一世。真正優雅的,一定有包容萬物、寬待衆生的胸懷;真正高貴的,面對強於己者不卑不亢,面對弱於己者平等視之。





websocket協議

1.1 背景html

1.2 協議概覽java

協議包含兩部分:握手,數據傳輸。linux

客戶端的握手以下:
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
web

服務端的握手以下:
        HTTP/1.1 101 Switching Protocols
        Upgrade: websocket
        Connection: Upgrade
        Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
        Sec-WebSocket-Protocol: chat
客戶端和服務端都發送了握手,而且成功,數據傳輸便可開始。
 
1.3 發起握手
發起握手是爲了兼容基於HTTP的服務端程序,這樣一個端口能夠同時處理HTTP客戶端和WebSocket客戶端
所以WebSocket客戶端握手是一個HTTP Upgrade請求:
        GET /chat HTTP/1.1
        Host: server.example.com
        Upgrade: websocket
        Connection: Upgrade
        Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
        Origin: http://example.com
        Sec-WebSocket-Protocol: chat, superchat
        Sec-WebSocket-Version: 13
握手中的域的順序是任意的。
 
5 數據幀
5.1 概述
WebScoket協議中,數據以幀序列的形式傳輸。
考慮到數據安全性,客戶端向服務器傳輸的數據幀必須進行掩碼處理。服務器若接收到未通過掩碼處理的數據幀,則必須主動關閉鏈接。
服務器向客戶端傳輸的數據幀必定不能進行掩碼處理。客戶端若接收到通過掩碼處理的數據幀,則必須主動關閉鏈接。
針對上狀況,發現錯誤的一方可向對方發送close幀(狀態碼是1002,表示協議錯誤),以關閉鏈接。
5.2 幀協議
WebSocket數據幀結構以下圖所示:
      0                   1                   2                   3
      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
     +-+-+-+-+-------+-+-------------+-------------------------------+
     |F|R|R|R| opcode|M| Payload len |    Extended payload length    |
     |I|S|S|S|  (4)  |A|     (7)     |             (16/64)           |
     |N|V|V|V|       |S|             |   (if payload len==126/127)   |
     | |1|2|3|       |K|             |                               |
     +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
     |     Extended payload length continued, if payload len == 127  |
     + - - - - - - - - - - - - - - - +-------------------------------+
     |                               |Masking-key, if MASK set to 1  |
     +-------------------------------+-------------------------------+
     | Masking-key (continued)       |          Payload Data         |
     +-------------------------------- - - - - - - - - - - - - - - - +
     :                     Payload Data continued ...                :
     + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
     |                     Payload Data continued ...                |
     +---------------------------------------------------------------+
 
FIN:1位
表示這是消息的最後一幀(結束幀),一個消息由一個或多個數據幀構成。若消息由一幀構成,起始幀即結束幀。
 
RSV1,RSV2,RSV3:各1位
MUST be 0 unless an extension is negotiated that defines meanings for non-zero values. If a nonzero value is received and none of the negotiated extensions defines the meaning of such a nonzero value, the receiving endpoint MUST _Fail the WebSocket Connection_.
這裏我翻譯很差,大體意思是若是未定義擴展,各位是0;若是定義了擴展,即爲非0值。若是接收的幀此處非0,擴展中卻沒有該值的定義,那麼關閉鏈接。
 
OPCODE:4位
解釋PayloadData,若是接收到未知的opcode,接收端必須關閉鏈接。
0x0表示附加數據幀
0x1表示文本數據幀
0x2表示二進制數據幀
0x3-7暫時無定義,爲之後的非控制幀保留
0x8表示鏈接關閉
0x9表示ping
0xA表示pong
0xB-F暫時無定義,爲之後的控制幀保留
 
MASK:1位
用於標識PayloadData是否通過掩碼處理。若是是1,Masking-key域的數據便是掩碼密鑰,用於解碼PayloadData。客戶端發出的數據幀須要進行掩碼處理,因此此位是1。
 
Payload length:7位,7+16位,7+64位
PayloadData的長度(以字節爲單位)。
若是其值在0-125,則是payload的真實長度。
若是值是126,則後面2個字節造成的16位無符號整型數的值是payload的真實長度。注意,網絡字節序,須要轉換。
若是值是127,則後面8個字節造成的64位無符號整型數的值是payload的真實長度。注意,網絡字節序,須要轉換。
長度表示遵循一個原則,用最少的字節表示長度(我理解是儘可能減小沒必要要的傳輸)。舉例說,payload真實長度是124,在0-125之間,必須用前7位表示;不容許長度1是126或127,而後長度2是124,這樣違反原則。
Payload長度是ExtensionData長度與ApplicationData長度之和。ExtensionData長度多是0,這種狀況下,Payload長度便是ApplicationData長度。
 
 
WebSocket協議規定數據經過幀序列傳輸。
客戶端必須對其發送到服務器的全部幀進行掩碼處理。
服務器一旦收到無掩碼幀,將關閉鏈接。服務器可能發送一個狀態碼是1002(表示協議錯誤)的Close幀。
而服務器發送客戶端的數據幀不作掩碼處理,一旦客戶端發現通過掩碼處理的幀,將關閉鏈接。客戶端可能使用狀態碼1002。
 

消息分片chrome

分片目的是發送長度未知的消息。若是不分片發送,即一幀,就須要緩存整個消息,計算其長度,構建frame併發送;使用分片的話,可以使用一個大小合適的buffer,用消息內容填充buffer,填滿即發送出去。api

分片規則:緩存

1.一個未分片的消息只有一幀(FIN爲1,opcode非0)安全

2.一個分片的消息由起始幀(FIN爲0,opcode非0),若干(0個或多個)幀(FIN爲0,opcode爲0),結束幀(FIN爲1,opcode爲0)。服務器

3.控制幀能夠出如今分片消息中間,但控制幀自己不容許分片。websocket

4.分片消息必須按次序逐幀發送。

5.若是未協商擴展的狀況下,兩個分片消息的幀之間不容許交錯。

6.可以處理存在於分片消息幀之間的控制幀

7.發送端爲非控制消息構建長度任意的分片

8.client和server兼容接收分片消息與非分片消息

9.控制幀不容許分片,中間媒介不容許改變分片結構(即爲控制幀分片)

10.若是使用保留位,中間媒介不知道其值表示的含義,那麼中間媒介不容許改變消息的分片結構

11.若是協商擴展,中間媒介不知道,那麼中間媒介不容許改變消息的分片結構,一樣地,若是中間媒介不瞭解一個鏈接的握手信息,也不容許改變該鏈接的消息的分片結構

12.因爲上述規則,一個消息的全部分片是同一數據類型(由第一個分片的opcode定義)的數據。由於控制幀不容許分片,因此一個消息的全部分片的數據類型是文本、二進制、opcode保留類型中的一種。

須要注意的是,若是控制幀不容許夾雜在一個消息的分片之間,延遲會較大,好比說當前正在傳輸一個較大的消息,此時的ping必須等待消息傳輸完成,才能發送出去,會致使較大的延遲。爲了不相似問題,須要容許控制幀夾雜在消息分片之間。

控制幀

  • linux cwebservice server code

  • 在HTML5中新增了WebSocket,使得通信變得更加方便。這樣一來,Web與硬件的交互除了CGI和XHR的方式外,又有了一個新的方式。那麼使用WebSocket又如何與下層通訊呢?看看WebSocket的相關介紹就會發現,其相似於HTTP協議的通訊,但又不一樣於HTTP協議通訊,其最終使用的是TCP通訊。具體的能夠參照該文WebScoket 規範 + WebSocket 協議。

    咱們先來看看通訊的效果圖

    \

    \

    下面是實現的步驟

    1.創建SOCKET監聽

    WebSocket也是TCP通訊,因此服務端須要先創建監聽,下面是實現的代碼。

     

    01. /* server.c */
    02. #include <stdio.h>
    03. #include <stdlib.h>
    04. #include <string.h>
    05. #include <unistd.h>
    06. #include <sys socket.h="">
    07. #include <netinet in.h="">
    08.  
    09. #include "base64.h"
    10. #include "sha1.h"
    11. #include "intLib.h"
    12.  
    13.  
    14. #define REQUEST_LEN_MAX 1024
    15. #define DEFEULT_SERVER_PORT 8000
    16. #define WEB_SOCKET_KEY_LEN_MAX 256
    17. #define RESPONSE_HEADER_LEN_MAX 1024
    18. #define LINE_MAX 256
    19.  
    20.  
    21. void shakeHand(int connfd,const char *serverKey);
    22. char * fetchSecKey(const char * buf);
    23. char * computeAcceptKey(const char * buf);
    24. char * analyData(const char * buf,const int bufLen);
    25. char * packData(const char * message,unsigned long * len);
    26. void response(const int connfd,const char * message);
    27.  
    28. int main(int argc, char *argv[])
    29. {
    30. struct sockaddr_in servaddr, cliaddr;
    31. socklen_t cliaddr_len;
    32. int listenfd, connfd;
    33. char buf[REQUEST_LEN_MAX];
    34. char *data;
    35. char str[INET_ADDRSTRLEN];
    36. char *secWebSocketKey;
    37. int i,n;
    38. int connected=0;//0:not connect.1:connected.
    39. int port= DEFEULT_SERVER_PORT;
    40.  
    41. if(argc>1)
    42. {
    43. port=atoi(argv[1]);
    44. }
    45. if(port<=0||port>0xFFFF)
    46. {
    47. printf("Port(%d) is out of range(1-%d)
    48. ",port,0xFFFF);
    49. return;
    50. }
    51. listenfd = socket(AF_INET, SOCK_STREAM, 0);
    52.  
    53. bzero(&servaddr, sizeof(servaddr));
    54. servaddr.sin_family = AF_INET;
    55. servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    56. servaddr.sin_port = htons(port);
    57.  
    58. bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
    59.  
    60. listen(listenfd, 20);
    61.  
    62. printf("Listen %d
    63. Accepting connections ...
    64. ",port);
    65. cliaddr_len = sizeof(cliaddr);
    66. connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len);
    67. printf("From %s at PORT %d
    68. ",
    69. inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)),
    70. ntohs(cliaddr.sin_port));
    71.  
    72. while (1)
    73. {
    74.  
    75. memset(buf,0,REQUEST_LEN_MAX);
    76. n = read(connfd, buf, REQUEST_LEN_MAX);
    77. printf("---------------------
    78. ");
    79.  
    80.  
    81. if(0==connected)
    82. {
    83. printf("read:%d
    84. %s
    85. ",n,buf);
    86. secWebSocketKey=computeAcceptKey(buf); 
    87. shakeHand(connfd,secWebSocketKey);
    88. connected=1;
    89. continue;
    90. }
    91.  
    92. data=analyData(buf,n);
    93. response(connfd,data);
    94. }
    95. close(connfd);
    96. }</netinet></sys></unistd.h></string.h></stdlib.h></stdio.h>

     

    2.握手

     

    在創建監聽後,網頁向服務端發現WebSocket請求,這時須要先進行握手。握手時,客戶端會在協議中包含一個握手的惟一Key,服務端在拿到這個Key後,須要加入一個GUID,而後進行sha1的加密,再轉換成base64,最後再發回到客戶端。這樣就完成了一次握手。此種握手方式是針對chrome websocket 13的版本,其餘版本的可能會有所不一樣。下面是實現的代碼。

     

    001. char * fetchSecKey(const char * buf)
    002. {
    003. char *key;
    004. char *keyBegin;
    005. char *flag="Sec-WebSocket-Key: ";
    006. int i=0, bufLen=0;
    007.  
    008. key=(char *)malloc(WEB_SOCKET_KEY_LEN_MAX);
    009. memset(key,0, WEB_SOCKET_KEY_LEN_MAX);
    010. if(!buf)
    011. {
    012. return NULL;
    013. }
    014.  
    015. keyBegin=strstr(buf,flag);
    016. if(!keyBegin)
    017. {
    018. return NULL;
    019. }
    020. keyBegin+=strlen(flag);
    021.  
    022. bufLen=strlen(buf);
    023. for(i=0;i<buflen;i++) 1.1="" 101="" char="" clientkey="(char" const="" guid="258EAFA5-E914-47DA-95CA-C5AB0DC85B11" http="" i="" int="" n="" pre="" protocols="" response=""responseheader="" return="" s="" sconnection:="" serverkey="base64_encode(sha1Data,"sha1data="(char" sha1datatemp="sha1_hash(clientKey);" short="" ssec-websocket-accept:="" supgrade:="" switching="" upgrade="" void="" websocket="">
    024.  
    025.  
    026. 注意:<p> </p><p>1.Connection後面的值與HTTP通訊時的不同了,是Upgrade,而Upgrade又對應到了websocket,這樣就標識了該通訊協議是websocket的方式。</p><p>2.在sha1加密後進行base64編碼時,使用sha1加密後的串必須將其當成16進制的字符串,將每兩個字符合成一個新的碼(0-0xFF間)來進一步計算後,才能夠進行base64換算(我開始時就在這裏折騰了好久,後面才弄明白還要加上這一步),若是是直接就base64,那就會握手失敗。</p><p>3.對於sha1和base64網上有不少,後面也附上我所使用的代碼。</p><h3>3.數據傳輸</h3><p>握手成功後就能夠進行數據傳輸了,只要按照WebSocket的協議來解就能夠了。下面是實現的代碼</p><p> </p><pre class="brush:java;">char * analyData(const char * buf,const int bufLen)
    027. {
    028. char * data;
    029. char fin, maskFlag,masks[4];
    030. char * payloadData;
    031. char temp[8];
    032. unsigned long n, payloadLen=0;
    033. unsigned short usLen=0;
    034. int i=0;
    035.  
    036.  
    037. if (bufLen < 2)
    038. {
    039. return NULL;
    040. }
    041.  
    042. fin = (buf[0] & 0x80) == 0x80// 1bit,1表示最後一幀 
    043. if (!fin)
    044. {
    045. return NULL;// 超過一幀暫不處理
    046. }
    047.  
    048. maskFlag = (buf[1] & 0x80) == 0x80// 是否包含掩碼 
    049. if (!maskFlag)
    050. {
    051. return NULL;// 不包含掩碼的暫不處理
    052. }
    053.  
    054. payloadLen = buf[1] & 0x7F// 數據長度
    055. if (payloadLen == 126)
    056. {     
    057. memcpy(masks,buf+44);     
    058. payloadLen =(buf[2]&0xFF) << 8 | (buf[3]&0xFF); 
    059. payloadData=(char *)malloc(payloadLen);
    060. memset(payloadData,0,payloadLen);
    061. memcpy(payloadData,buf+8,payloadLen);
    062. }
    063. else if (payloadLen == 127)
    064. {
    065. memcpy(masks,buf+10,4); 
    066. for ( i = 0; i < 8; i++)
    067. {
    068. temp[i] = buf[9 - i];
    069. }
    070.  
    071. memcpy(&n,temp,8); 
    072. payloadData=(char *)malloc(n);
    073. memset(payloadData,0,n);
    074. memcpy(payloadData,buf+14,n);//toggle error(core dumped) if data is too long.
    075. payloadLen=n;   
    076. }
    077. else
    078. {  
    079. memcpy(masks,buf+2,4);   
    080. payloadData=(char *)malloc(payloadLen);
    081. memset(payloadData,0,payloadLen);
    082. memcpy(payloadData,buf+6,payloadLen);
    083. }
    084.  
    085. for (i = 0; i < payloadLen; i++)
    086. {
    087. payloadData[i] = (char)(payloadData[i] ^ masks[i % 4]);
    088. }
    089.  
    090. printf("data(%d):%s
    091. ",payloadLen,payloadData);
    092. return payloadData;
    093. }
    094.  
    095. char *  packData(const char * message,unsigned long * len)
    096. {
    097. char * data=NULL;
    098. unsigned long n;
    099.  
    100. n=strlen(message);
    101. if (n < 126)
    102. {
    103. data=(char *)malloc(n+2);
    104. memset(data,0,n+2);   
    105. data[0] = 0x81;
    106. data[1] = n;
    107. memcpy(data+2,message,n);
    108. *len=n+2;
    109. }
    110. else if (n < 0xFFFF)
    111. {
    112. data=(char *)malloc(n+4);
    113. memset(data,0,n+4);
    114. data[0] = 0x81;
    115. data[1] = 126;
    116. data[2] = (n>>8 0xFF);
    117. data[3] = (n & 0xFF);
    118. memcpy(data+4,message,n);   
    119. *len=n+4;
    120. }
    121. else
    122. {
    123.  
    124. // 暫不處理超長內容 
    125. *len=0;
    126. }
    127.  
    128.  
    129. return data;
    130. }
    131.  
    132. void response(int connfd,const char * message)
    133. {
    134. char * data;
    135. unsigned long n=0;
    136. int i;
    137. if(!connfd)
    138. {
    139. return;
    140. }
    141.  
    142. if(!data)
    143. {
    144. return;
    145. }
    146. data=packData(message,&n);
    147.  
    148. if(!data||n<=0)
    149. {
    150. printf("data is empty!
    151. ");
    152. return;
    153. }
    154.  
    155. write(connfd,data,n);
    156.  
    157. }</pre>
    158. <br>
    159. 注意:
    160. <p> </p>
    161. <p>1.對於超過0xFFFF長度的數據在分析數據部分雖然做了處理,可是在memcpy時會報core dumped的錯誤,沒有解決,請過路的大牛幫忙指點。在packData部分也未對這一部分做處理。</p>
    162. <p>2.在這裏碰到了一個鬱悶的問題,在命名函數時,將函數名寫的過長了(fetchSecWebSocketAcceptkey),結果致使編譯經過,但在運行時卻莫名其妙的報core dumped的錯誤,試了不少方法才發現是這個緣由,後將名字改短後就OK了。</p>
    163. <p>3.在回覆數據時,只要按websocket的協議進行迴應就能夠了。</p>
    164. <p>附上sha一、base64和intLib的代碼(sha1和base64是從網上摘來的)</p>
    165. <p>sha1.h</p>
    166. <p> </p>
    167. <pre class="brush:java;">//sha1.h:對字符串進行sha1加密
    168. #ifndef _SHA1_H_
    169. #define _SHA1_H_
    170.  
    171. #include <stdio.h>
    172. #include <stdlib.h>
    173. #include <string.h>
    174.  
    175.  
    176. typedef struct SHA1Context{
    177. unsigned Message_Digest[5];     
    178. unsigned Length_Low;            
    179. unsigned Length_High;           
    180. unsigned char Message_Block[64];
    181. int Message_Block_Index;        
    182. int Computed;                   
    183. int Corrupted;                  
    184. } SHA1Context;
    185.  
    186. void SHA1Reset(SHA1Context *);
    187. int SHA1Result(SHA1Context *);
    188. void SHA1Input( SHA1Context *,const char *,unsigned);
    189. #endif
    190.  
    191.  
    192. #define SHA1CircularShift(bits,<a href="http://www.it165.net/edu/ebg/" target="_blank"class="keylink">word</a>) ((((<a href="http://www.it165.net/edu/ebg/" target="_blank"class="keylink">word</a>) << (bits)) & 0xFFFFFFFF) | ((word) >> (32-(bits))))
    193.  
    194. void SHA1ProcessMessageBlock(SHA1Context *);
    195. void SHA1PadMessage(SHA1Context *);
    196.  
    197. void SHA1Reset(SHA1Context *context){// 初始化動做
    198. context->Length_Low             = 0;
    199. context->Length_High            = 0;
    200. context->Message_Block_Index    = 0;
    201.  
    202. context->Message_Digest[0]      = 0x67452301;
    203. context->Message_Digest[1]      = 0xEFCDAB89;
    204. context->Message_Digest[2]      = 0x98BADCFE;
    205. context->Message_Digest[3]      = 0x10325476;
    206. context->Message_Digest[4]      = 0xC3D2E1F0;
    207.  
    208. context->Computed   = 0;
    209. context->Corrupted  = 0;
    210. }
    211.  
    212.  
    213. int SHA1Result(SHA1Context *context){// 成功返回1,失敗返回0
    214. if (context->Corrupted) {
    215. return 0;
    216. }
    217. if (!context->Computed) {
    218. SHA1PadMessage(context);
    219. context->Computed = 1;
    220. }
    221. return 1;
    222. }
    223.  
    224.  
    225. void SHA1Input(SHA1Context *context,const char *message_array,unsigned length){
    226. if (!length) return;
    227.  
    228. if (context->Computed || context->Corrupted){
    229. context->Corrupted = 1;
    230. return;
    231. }
    232.  
    233. while(length-- && !context->Corrupted){
    234. context->Message_Block[context->Message_Block_Index++] = (*message_array & 0xFF);
    235.  
    236. context->Length_Low += 8;
    237.  
    238. context->Length_Low &= 0xFFFFFFFF;
    239. if (context->Length_Low == 0){
    240. context->Length_High++;
    241. context->Length_High &= 0xFFFFFFFF;
    242. if (context->Length_High == 0) context->Corrupted = 1;
    243. }
    244.  
    245. if (context->Message_Block_Index == 64){
    246. SHA1ProcessMessageBlock(context);
    247. }
    248. message_array++;
    249. }
    250. }
    251.  
    252. void SHA1ProcessMessageBlock(SHA1Context *context){
    253. const unsigned K[] = {0x5A8279990x6ED9EBA10x8F1BBCDC0xCA62C1D6 };
    254. int         t;               
    255. unsigned    temp;            
    256. unsigned    W[80];           
    257. unsigned    A, B, C, D, E;   
    258.  
    259. for(t = 0; t < 16; t++) {
    260. W[t] = ((unsigned) context->Message_Block[t * 4]) << 24;
    261. W[t] |= ((unsigned) context->Message_Block[t * 4 1]) << 16;
    262. W[t] |= ((unsigned) context->Message_Block[t * 4 2]) << 8;
    263. W[t] |= ((unsigned) context->Message_Block[t * 4 3]);
    264. }
    265.  
    266. for(t = 16; t < 80; t++)  W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
    267.  
    268. A = context->Message_Digest[0];
    269. B = context->Message_Digest[1];
    270. C = context->Message_Digest[2];
    271. D = context->Message_Digest[3];
    272. E = context->Message_Digest[4];
    273.  
    274. for(t = 0; t < 20; t++) {
    275. temp =  SHA1CircularShift(5,A) + ((B & C) | ((~B) & D)) + E + W[t] + K[0];
    276. temp &= 0xFFFFFFFF;
    277. E = D;
    278. D = C;
    279. C = SHA1CircularShift(30,B);
    280. B = A;
    281. A = temp;
    282. }
    283. for(t = 20; t < 40; t++) {
    284. temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
    285. temp &= 0xFFFFFFFF;
    286. E = D;
    287. D = C;
    288. C = SHA1CircularShift(30,B);
    289. B = A;
    290. A = temp;
    291. }
    292. for(t = 40; t < 60; t++) {
    293. temp = SHA1CircularShift(5,A) + ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
    294. temp &= 0xFFFFFFFF;
    295. E = D;
    296. D = C;
    297. C = SHA1CircularShift(30,B);
    298. B = A;
    299. A = temp;
    300. }
    301. for(t = 60; t < 80; t++) {
    302. temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
    303. temp &= 0xFFFFFFFF;
    304. E = D;
    305. D = C;
    306. C = SHA1CircularShift(30,B);
    307. B = A;
    308. A = temp;
    309. }
    310. context->Message_Digest[0] = (context->Message_Digest[0] + A) & 0xFFFFFFFF;
    311. context->Message_Digest[1] = (context->Message_Digest[1] + B) & 0xFFFFFFFF;
    312. context->Message_Digest[2] = (context->Message_Digest[2] + C) & 0xFFFFFFFF;
    313. context->Message_Digest[3] = (context->Message_Digest[3] + D) & 0xFFFFFFFF;
    314. context->Message_Digest[4] = (context->Message_Digest[4] + E) & 0xFFFFFFFF;
    315. context->Message_Block_Index = 0;
    316. }
    317.  
    318. void SHA1PadMessage(SHA1Context *context){
    319. if (context->Message_Block_Index > 55) {
    320. context->Message_Block[context->Message_Block_Index++] = 0x80;
    321. while(context->Message_Block_Index < 64)  context->Message_Block[context->Message_Block_Index++] = 0;
    322. SHA1ProcessMessageBlock(context);
    323. while(context->Message_Block_Index < 56) context->Message_Block[context->Message_Block_Index++] = 0;
    324. else {
    325. context->Message_Block[context->Message_Block_Index++] = 0x80;
    326. while(context->Message_Block_Index < 56) context->Message_Block[context->Message_Block_Index++] = 0;
    327. }
    328. context->Message_Block[56] = (context->Length_High >> 24 ) & 0xFF;
    329. context->Message_Block[57] = (context->Length_High >> 16 ) & 0xFF;
    330. context->Message_Block[58] = (context->Length_High >> 8 ) & 0xFF;
    331. context->Message_Block[59] = (context->Length_High) & 0xFF;
    332. context->Message_Block[60] = (context->Length_Low >> 24 ) & 0xFF;
    333. context->Message_Block[61] = (context->Length_Low >> 16 ) & 0xFF;
    334. context->Message_Block[62] = (context->Length_Low >> 8 ) & 0xFF;
    335. context->Message_Block[63] = (context->Length_Low) & 0xFF;
    336.  
    337. SHA1ProcessMessageBlock(context);
    338. }
    339.  
    340. /*
    341. int sha1_hash(const char *source, char *lrvar){// Main
    342. SHA1Context sha;
    343. char buf[128];
    344.  
    345. SHA1Reset(&sha);
    346. SHA1Input(&sha, source, strlen(source));
    347.  
    348. if (!SHA1Result(&sha)){
    349. printf("SHA1 ERROR: Could not compute message digest");
    350. return -1;
    351. } else {
    352. memset(buf,0,sizeof(buf));
    353. sprintf(buf, "%08X%08X%08X%08X%08X", sha.Message_Digest[0],sha.Message_Digest[1],
    354. sha.Message_Digest[2],sha.Message_Digest[3],sha.Message_Digest[4]);
    355. //lr_save_string(buf, lrvar);
    356.  
    357. return strlen(buf);
    358. }
    359. }
    360. */
    361.  
    362. char * sha1_hash(const char *source){// Main
    363. SHA1Context sha;
    364. char *buf;//[128];
    365.  
    366. SHA1Reset(&sha);
    367. SHA1Input(&sha, source, strlen(source));
    368.  
    369. if (!SHA1Result(&sha)){
    370. printf("SHA1 ERROR: Could not compute message digest");
    371. return NULL;
    372. else {
    373. buf=(char *)malloc(128);
    374. memset(buf,0,sizeof(buf));
    375. sprintf(buf, "%08X%08X%08X%08X%08X", sha.Message_Digest[0],sha.Message_Digest[1],
    376. sha.Message_Digest[2],sha.Message_Digest[3],sha.Message_Digest[4]);
    377. //lr_save_string(buf, lrvar);
    378.  
    379. //return strlen(buf);
    380. return buf;
    381. }
    382. }
    383. </string.h></stdlib.h></stdio.h></pre>
    384. <br>
    385. base64.h
    386. <p> </p>
    387. <p> </p>
    388. <pre class="brush:java;">#ifndef _BASE64_H_
    389. #define _BASE64_H_
    390.  
    391. #include <stdio.h>
    392. #include <stdlib.h>
    393. #include <string.h>
    394.  
    395. const char base[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    396. char* base64_encode(const char* data, int data_len);
    397. char *base64_decode(const char* data, int data_len);
    398. static char find_pos(char ch);
    399.  
    400. /* */
    401. char *base64_encode(const char* data, int data_len)
    402. {
    403. //int data_len = strlen(data);
    404. int prepare = 0;
    405. int ret_len;
    406. int temp = 0;
    407. char *ret = NULL;
    408. char *f = NULL;
    409. int tmp = 0;
    410. char changed[4];
    411. int i = 0;
    412. ret_len = data_len / 3;
    413. temp = data_len % 3;
    414. if (temp > 0)
    415. {
    416. ret_len += 1;
    417. }
    418. ret_len = ret_len*4 1;
    419. ret = (char *)malloc(ret_len);
    420.  
    421. if ( ret == NULL)
    422. {
    423. printf("No enough memory.
    424. ");
    425. exit(0);
    426. }
    427. memset(ret, 0, ret_len);
    428. f = ret;
    429. while (tmp < data_len)
    430. {
    431. temp = 0;
    432. prepare = 0;
    433. memset(changed, ''4);
    434. while (temp < 3)
    435. {
    436. //printf("tmp = %d
    437. ", tmp);
    438. if (tmp >= data_len)
    439. {
    440. break;
    441. }
    442. prepare = ((prepare << 8) | (data[tmp] & 0xFF));
    443. tmp++;
    444. temp++;
    445. }
    446. prepare = (prepare<<((3-temp)*8));
    447. //printf("before for : temp = %d, prepare = %d
    448. ", temp, prepare);
    449. for (i = 0; i < 4 ;i++ )
    450. {
    451. if (temp < i)
    452. {
    453. changed[i] = 0x40;
    454. }
    455. else
    456. {
    457. changed[i] = (prepare>>((3-i)*6)) & 0x3F;
    458. }
    459. *f = base[changed[i]];
    460. //printf("%.2X", changed[i]);
    461. f++;
    462. }
    463. }
    464. *f = '';
    465.  
    466. return ret;
    467.  
    468. }
    469. /* */
    470. static char find_pos(char ch)  
    471. {
    472. char *ptr = (char*)strrchr(base, ch);//the last position (the only) in base[]
相關文章
相關標籤/搜索