test.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. #include <unistd.h>
  2. #include <limits.h>
  3. #include <stdlib.h>
  4. #include <stdint.h>
  5. #include <clock.h>
  6. #include <zio.h>
  7. #include <log.h>
  8. #include <zloop.h>
  9. #include "base64.h"
  10. #include "io_buf.h"
  11. struct web_client_http:ev::io
  12. {
  13. in_buff m_buff;
  14. int m_data_len=-1;
  15. int m_mask_pos=-1;
  16. int m_data_pos=-1;
  17. int m_fd,m_status;
  18. web_client_http()
  19. :m_buff(8192)
  20. {
  21. m_fd=-1;
  22. }
  23. int connect_tcp(const char*ip,int port)
  24. {
  25. int fd=zio::build_stream();
  26. if(zio::connect(fd,ip,port))
  27. {
  28. zio::close(fd);
  29. return m_fd=-1;
  30. }
  31. zio::setiobuf(fd,16<<10,16<<10);
  32. zio::setblocking(fd,false);
  33. return m_fd=fd;
  34. }
  35. void ws_reset()
  36. {
  37. if(m_data_pos+m_data_len>0)
  38. {
  39. m_buff.free(m_data_len+m_data_pos);
  40. }
  41. m_data_len=-1;
  42. m_mask_pos=-1;
  43. m_data_pos=-1;
  44. }
  45. bool ws_fin()const
  46. {
  47. return (m_buff[0]&0x80) != 0;
  48. }
  49. bool ws_more()const
  50. {
  51. return (m_buff[0]&0xF) ==0 ;
  52. }
  53. bool ws_text()const
  54. {
  55. return (m_buff[0]&0xF) ==1 ;
  56. }
  57. bool ws_bin()const
  58. {
  59. return (m_buff[0]&0xF) ==2 ;
  60. }
  61. bool ws_ping()const
  62. {
  63. return (m_buff[0]&0xF) ==9 ;
  64. }
  65. bool ws_pong()const
  66. {
  67. return (m_buff[0]&0xF) ==10 ;
  68. }
  69. bool ws_close()const
  70. {
  71. return (m_buff[0]&0xF) ==8 ;
  72. }
  73. bool ws_mask()const
  74. {
  75. return (m_buff[1]&0x80) !=0 ;
  76. }
  77. int parse_length()
  78. {
  79. if(m_buff.len_data()<2)
  80. return -1;
  81. if(m_data_pos>0)
  82. return 0;
  83. if((m_buff[1]&0x7F)<=125)
  84. {
  85. m_mask_pos=ws_mask()?2:-1;
  86. m_data_pos=ws_mask()?6:2;
  87. m_data_len=m_buff[1]&0x7F;
  88. }
  89. else
  90. if((m_buff[1]&0x7F)==126)
  91. {
  92. if(m_buff.len_data()<4)
  93. return -1;
  94. m_mask_pos=ws_mask()?4:-1;
  95. m_data_pos=ws_mask()?8:4;
  96. m_data_len=(m_buff[2]<<8) | m_buff[3];
  97. }
  98. else
  99. {
  100. if(m_buff.len_data()<9)
  101. return -1;
  102. m_mask_pos=ws_mask()?9:-1;
  103. m_data_pos=ws_mask()?13:9;
  104. //不考虑大于20G的数据
  105. m_data_len=(m_buff[6]<<24)|(m_buff[7]<<16)|(m_buff[8]<<8)|(m_buff[9]);
  106. }
  107. int i=0;
  108. for(i=0;i<m_data_len;i++)
  109. {
  110. uint8_t b=m_buff[m_data_pos+i];
  111. if(b>=0x30 && b<=0x39)
  112. continue;
  113. break;
  114. }
  115. m_data_len-=i;
  116. m_data_pos+=i;
  117. return 0;
  118. }
  119. void mask(const uint8_t*m,uint8_t*d,int len)
  120. {
  121. for(int i=0;i<len;i++)
  122. d[i]=d[i]^m[i&3];
  123. }
  124. int ws_parse()
  125. {
  126. if(parse_length()<0)
  127. return -1;
  128. if(m_buff.len_data()<m_data_pos+m_data_len)
  129. return -1;
  130. if(ws_mask())
  131. {
  132. mask(&m_buff[m_mask_pos],&m_buff[m_data_pos],m_data_len);
  133. }
  134. for(int i=0;i<m_data_len;i++)
  135. {
  136. printf("%c",m_buff[m_data_pos+i]);
  137. }
  138. printf("\n\n");
  139. return 0;
  140. }
  141. int connect_ws(const char*ip,int port)
  142. {
  143. unsigned char k[16], k6[128];
  144. for(size_t i=0;i<sizeof(k);i++)
  145. k[i]=rand();
  146. base64::encode(k,sizeof(k),k6);
  147. const char*fmt=
  148. "GET /socket.io/?EIO=3&transport=websocket HTTP/1.1\r\n"
  149. "Host: %s:%d\r\n"
  150. "Connection: Upgrade\r\n"
  151. "Pragma: no-cache\r\n"
  152. "Cache-Control: no-cache\r\n"
  153. "Upgrade: websocket\r\n"
  154. "Origin: http://%s:%d\r\n"
  155. "Sec-WebSocket-Version: 13\r\n"
  156. "Accept-Encoding: gzip, deflate\r\n"
  157. "Accept-Language: zh-CN,zh;q=0.9\r\n"
  158. "Sec-WebSocket-Key: %s\r\n"
  159. "Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits\r\n\r\n";
  160. if(connect_tcp(ip,port)<0)
  161. return -1;
  162. char buf[512];
  163. int len=sprintf(buf,fmt,ip,port,ip,port,k6);
  164. if(len!=zio::writev(m_fd, buf, len))
  165. {
  166. close();
  167. return -1;
  168. }
  169. sleep(1);
  170. if(read_until("\r\n\r\n")<=0)
  171. {
  172. close();
  173. return -1;
  174. }
  175. if(m_buff.find("101 Switching Protocols\r\n"))
  176. {
  177. m_buff.skip(m_buff.find("\r\n\r\n"));
  178. return 0;
  179. }
  180. close();
  181. return -1;
  182. }
  183. int read_until(const char*what,int timeout=10*1000)
  184. {
  185. int rc=0;
  186. zclock c;
  187. for(;;)
  188. {
  189. buff_t b=m_buff.alloc();
  190. if(b.empty())
  191. {
  192. m_buff.grow(1024);
  193. b=m_buff.alloc();
  194. }
  195. int len=zio::read(m_fd,b.ptr(),b.len());
  196. if((int)c.count_ms()>timeout)
  197. {
  198. log_error("websocket read timeout in %dms",timeout);
  199. return -1;
  200. }
  201. if(len==-1)
  202. {
  203. return -1;
  204. }
  205. if(len==-2)
  206. continue;
  207. if(len==0)
  208. {
  209. log_info("remote close the socket");
  210. return 0;
  211. }
  212. m_buff.commit(len);
  213. rc+=len;
  214. if(m_buff.find(what))
  215. return rc;
  216. }
  217. }
  218. void close()
  219. {
  220. zio::close(m_fd);
  221. }
  222. ~web_client_http()
  223. {
  224. close();
  225. }
  226. };
  227. int realpath_test()
  228. {
  229. char buf[4096];
  230. realpath(".",buf);
  231. log_info("curpath=%s",buf);
  232. return 0;
  233. }
  234. #if 0
  235. std::string test_json()
  236. {
  237. struct json
  238. {
  239. json&put(const char*k,const json&n)
  240. {
  241. return *this;
  242. }
  243. json&put(const char*k,int v)
  244. {
  245. return *this;
  246. }
  247. json&put(const char*k,const char*v)
  248. {
  249. return *this;
  250. }
  251. std::string to_string()const
  252. {
  253. return std::string();
  254. }
  255. };
  256. return json().put("cmd","login")
  257. .put("data",json()
  258. .put("uname","wyj")
  259. .put("passwd",111111)
  260. ).to_string();
  261. }
  262. #endif
  263. int main()
  264. {
  265. unsigned char buf[32];
  266. const char*s64="puVOuWb7rel6z2AVZBKnfw==";
  267. int blen=32;
  268. base64::decode((char*)s64,strlen(s64),buf,blen);
  269. web_client_http client;
  270. client.connect_ws("60.220.238.150",8086);
  271. for(;;)
  272. {
  273. while(client.ws_parse()==0)
  274. client.ws_reset();
  275. client.read_until("\n");
  276. }
  277. return 0;
  278. }