道法天然 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 大智者必謙和,大善者必寬容。惟有小智者才咄咄逼人,小善者才斤斤計較。大氣象者,不講排場;講大排場者,露小氣象。大成者謙遜平和,小成者不可一世。真正優雅的,一定有包容萬物、寬待衆生的胸懷;真正高貴的,面對強於己者不卑不亢,面對弱於己者平等視之。
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: 13web
服務端的握手以下: 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必須等待消息傳輸完成,才能發送出去,會致使較大的延遲。爲了不相似問題,須要容許控制幀夾雜在消息分片之間。
控制幀
在HTML5中新增了WebSocket,使得通信變得更加方便。這樣一來,Web與硬件的交互除了CGI和XHR的方式外,又有了一個新的方式。那麼使用WebSocket又如何與下層通訊呢?看看WebSocket的相關介紹就會發現,其相似於HTTP協議的通訊,但又不一樣於HTTP協議通訊,其最終使用的是TCP通訊。具體的能夠參照該文WebScoket 規範 + WebSocket 協議。
咱們先來看看通訊的效果圖
下面是實現的步驟
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>
在創建監聽後,網頁向服務端發現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+
4
,
4
);
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[] = {
0x5A827999
,
0x6ED9EBA1
,
0x8F1BBCDC
,
0xCA62C1D6
};
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[]