Guest User

Untitled

a guest
Dec 4th, 2017
340
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.43 KB | None | 0 0
  1.  
  2. ' FRAME DECODING: http://tools.ietf.org/html/rfc6455 -- See "5.2. Base Framing Protocol"
  3.  
  4. ' Code by Nilium -- used by Base64 functions!
  5.  
  6. Const etable$ = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
  7. Global dtable@[256]
  8.  
  9. ' Basic WebSockets server...
  10.  
  11. ' For testing, use:
  12.  
  13. ' http://www.websocket.org/echo.html
  14.  
  15. ' or this Chrome extension:
  16.  
  17. ' https://chrome.google.com/webstore/detail/pfdhoblngboilpfeibdedpjgfnlcodoo
  18.  
  19. ' Misc...
  20.  
  21. Rem
  22.  
  23. http://tools.ietf.org/html/rfc6455#page-36
  24. http://www.htmlgoodies.com/html5/tutorials/making-html5-websockets-work.html#fbid=MQV91wYw7gh
  25. http://www.developerfusion.com/article/143158/an-introduction-to-websockets/
  26. http://www.websocket.org/aboutwebsocket.html
  27. http://www.altdevblogaday.com/2012/01/23/writing-your-own-websocket-server/
  28.  
  29. End Rem
  30.  
  31. Const WS_MAGIC:String = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
  32.  
  33. Const BIT_FIN:Int = 0
  34. Const BIT_RSV1:Int = 1
  35. Const BIT_RSV2:Int = 2
  36. Const BIT_RSV3:Int = 3
  37. Const BIT_MASK:Int = 8
  38.  
  39. InitBase64
  40.  
  41. Local tcp:TSocket = CreateTCPSocket ()
  42.  
  43. If Not tcp Then RuntimeError "No TCP socket!"
  44.  
  45. If Not BindSocket (tcp, 80) Then CloseSocket tcp; RuntimeError "Couldn't bind TCP to port 80!"
  46.  
  47. SocketListen tcp, 5
  48.  
  49. Repeat
  50.  
  51. Local incoming:TSocket = SocketAccept (tcp)
  52.  
  53. If incoming
  54.  
  55. Local stream:TStream = CreateSocketStream (incoming)
  56.  
  57. If stream
  58.  
  59. Local message:String = ""
  60.  
  61. While Not Eof (stream)
  62.  
  63. If SocketReadAvail (incoming)
  64.  
  65. message = ReadLine (stream)
  66.  
  67. Print "MSG: " + message
  68.  
  69. Select message
  70.  
  71. Case ""
  72.  
  73. If incoming And stream
  74.  
  75. WriteLine stream, "HTTP/1.1 101 Switching Protocols"
  76. WriteLine stream, "Upgrade: websocket"
  77. WriteLine stream, "Connection: Upgrade"
  78. WriteLine stream, "Sec-WebSocket-Accept: " + accept
  79. WriteLine stream, ""
  80.  
  81. Local msg:String = ""
  82.  
  83. ' Do stuff!
  84.  
  85. Repeat
  86.  
  87. Local bytes:TBank = FillBank (incoming, stream)
  88.  
  89. If bytes
  90.  
  91. Local chars:String = ""
  92.  
  93. For Local loop:Int = 0 Until BankSize (bytes)
  94.  
  95. Print ""
  96. Print "New byte!"
  97. Print ""
  98.  
  99. Local _byte:Byte = PeekByte (bytes, loop)
  100. Print "Byte: " + _byte
  101.  
  102. chars = chars + _byte
  103.  
  104. Local bytearray:Byte [] = [0:Byte, 0:Byte, 0:Byte, 0:Byte, 0:Byte, 0:Byte, 0:Byte, 0:Byte]
  105.  
  106. For Local byteloop:Int = 0 To 7
  107. bytearray [byteloop] = _byte & 1 Shl byteloop
  108. Next
  109.  
  110. 'Const BIT_FIN:Int = 0
  111. 'Const BIT_RSV1:Int = 1
  112. 'Const BIT_RSV2:Int = 2
  113. 'Const BIT_RSV3:Int = 3
  114. 'Const BIT_MASK:Int = 8
  115.  
  116. If bytearray [BIT_FIN] Then Print "FIN marker set -- final fragment in message."
  117. If bytearray [BIT_RSV1] Then Print "RSV1 marker set -- no extensions supported, should terminate!"
  118. If bytearray [BIT_RSV2] Then Print "RSV2 marker set -- no extensions supported, should terminate!"
  119. If bytearray [BIT_RSV3] Then Print "RSV3 marker set -- no extensions supported, should terminate!"
  120. 'If bytearray [BIT_MASK] Then Print "MASK marker set -- message contents are masked."
  121.  
  122. Local opcode:Short = (bytearray [7] | bytearray [6] | bytearray [5] | bytearray [4]) Shr 1
  123.  
  124. Print Bin (_byte)
  125. Print "Opcode: $" + Hex (opcode)
  126. Print ""
  127.  
  128. Select opcode
  129. Case $0
  130. Print "Continuation frame"
  131. Case $1
  132. Print "Text frame"
  133. Case $2
  134. Print "Binary frame"
  135. Case $3, $4, $5, $6, $7
  136. Print "Reserved data frame opcode"
  137. Case $8
  138. Print "Connection close"
  139. Case $9
  140. Print "Ping"
  141. Case $A
  142. Print "Pong"
  143. Case $B, $C, $D, $E, $F
  144. Print "Reserved control frame opcode"
  145. End Select
  146.  
  147. Next
  148.  
  149. chars = Left (chars, Len (chars) - 2)
  150.  
  151. Print "[" + chars + "]"
  152.  
  153. bytes = Null
  154.  
  155. EndIf
  156.  
  157. Forever
  158.  
  159. EndIf
  160.  
  161. Default
  162.  
  163. If Left (message, 19) = "Sec-WebSocket-Key: "
  164.  
  165. Local key:String = Right (message, Len (message) - 19)
  166. Local accept:String = CreateResponse (key)
  167.  
  168. EndIf
  169.  
  170. End Select
  171.  
  172. Else
  173. Delay 10
  174. EndIf
  175.  
  176. Wend
  177.  
  178. EndIf
  179.  
  180. Else
  181.  
  182. Print "Waiting for connection..."
  183. Delay 500
  184.  
  185. EndIf
  186.  
  187. Until KeyHit (KEY_ESCAPE)
  188.  
  189. If stream Then CloseStream stream
  190. If incoming Then CloseSocket incoming
  191. If tcp Then CloseSocket tcp
  192.  
  193. End
  194.  
  195. Function FillBank:TBank (socket:TSocket, stream:TStream)
  196.  
  197. Local getbytes:Int = SocketReadAvail (socket)
  198.  
  199. If getbytes
  200.  
  201. Print getbytes + " bytes received"
  202.  
  203. Local bank:TBank = CreateBank (getbytes)
  204.  
  205. If bank
  206. For Local loop:Int = 0 Until getbytes
  207. PokeByte bank, loop, ReadByte (stream)
  208. Next
  209. EndIf
  210.  
  211. EndIf
  212.  
  213. Return bank
  214.  
  215. End Function
  216.  
  217. ' Adds \r prior to \n, as required by WebSockets...
  218.  
  219. Function WriteLineR:Int (stream:TStream, str:String)
  220. WriteLine stream, str + "~r"
  221. End Function
  222.  
  223. Function CreateResponse:String (key:String)
  224.  
  225. ' To test using known-working data, uncomment either 'key' line below
  226. ' and compare the result (found in the 'response' string)...
  227.  
  228. ' From http://tools.ietf.org/html/rfc6455
  229. ' Result should be "s3pPLMBiTxaQ9kYGzzhZRbK+xOo="
  230.  
  231. ' key = "dGhlIHNhbXBsZSBub25jZQ=="
  232.  
  233. ' From http://en.wikipedia.org/wiki/WebSocket
  234. ' Result should be: "HSmrc0sMlYUkAGmm5OPpG2HaGWk="
  235.  
  236. ' key = "x3JJHMbDL1EzLkh9GBhXDw=="
  237.  
  238. ' From http://www.codeproject.com/Articles/209041/HTML5-Web-Socket-in-Essence
  239. ' Result should be: "VAuGgaNDB/reVQpGfDF8KXeZx5o="
  240.  
  241. ' key = "V2ViU29ja2V0IHJvY2tzIQ=="
  242.  
  243. key = SHA1 (key + WS_MAGIC)
  244.  
  245. Local keybytes:Byte [] = HexToByteArray (key)
  246. Local response:String = EncodeBase64 (keybytes, keybytes.Length)
  247.  
  248. Return response
  249.  
  250. End Function
  251.  
  252. Function HexToByteArray:Byte [] (hx:String)
  253.  
  254. Local bytes:Byte [Len (hx) / 2]
  255.  
  256. For Local loop:Int = 1 To Len (hx) Step 2
  257. bytes [loop / 2] = Byte ("$" + Mid (hx, loop, 2))
  258. Next
  259.  
  260. Return bytes
  261.  
  262. End Function
  263.  
  264. ' Code by Nilium!
  265.  
  266. Function InitBase64 ()
  267. For Local __di:Int = 0 To etable.Length-1
  268. dtable[etable[__di]] = __di
  269. Next
  270. End Function
  271.  
  272. Function EncodeBase64$( in@ Ptr, sizein:Int )
  273. If sizein <= 0 Then Return Null
  274. Local out:Byte[64]
  275. Local s$
  276.  
  277. Local p@ Ptr = out
  278. Local cc% = 0
  279.  
  280. For Local i% = 0 To sizein-1 Step 3
  281. Local c1@, c2@
  282. c1 = in[i]&$FF
  283. c2 = in[i+1]&$FF
  284.  
  285. p[0] = etable[in[0] Shr 2]
  286. If i+1 < sizein Then
  287. p[1] = etable[((in[0] & $3) Shl 4) | ((in[1] & $F0) Shr 4)]
  288. If i+2 < sizein Then
  289. p[2] = etable[((in[1] & $F) Shl 2) | ((in[2] & $C0) Shr 6)]
  290. p[3] = etable[in[2] & $3F]
  291. ElseIf i+1 < sizein Then
  292. p[2] = etable[((in[1] & $F) Shl 2)]
  293. EndIf
  294. Else
  295. p[1] = etable[((in[0] & $3) Shl 4)]
  296. EndIf
  297.  
  298. in :+ 3
  299. p :+ 4
  300. cc :+ 4
  301. If cc = 64 Then
  302. s :+ String.FromBytes(out,cc)
  303. p = out
  304. cc = 0
  305. EndIf
  306. Next
  307. Select sizein Mod 3
  308. Case 0
  309. s :+ String.FromBytes(out, cc)
  310. Case 1
  311. s :+ String.FromBytes(out, cc-2)+"=="
  312. Case 2
  313. s :+ String.FromBytes(out, cc-1)+"="
  314. End Select
  315. Return s
  316. End Function
  317.  
  318. ' Assumes you're passing a valid string to it
  319. Function DecodeBase64:Byte[]( in$ )
  320. Local f% = in.Find("=")
  321. in = in.Replace("=","~0")
  322. Local rm% = 0
  323. If f = -1 Then
  324. rm = 0
  325. f = in.Length-1
  326. ElseIf f = in.Length-1 Then
  327. rm = 1
  328. ElseIf f = in.Length-2 Then
  329. rm = 2
  330. EndIf
  331. Local out@[((in.Length/4)*3)-rm]
  332. Local p@ Ptr = out
  333. Local bc% = 0
  334. For Local cc:Int = 0 To f Step 4
  335. p[0] = (dtable[in[cc]] Shl 2) | (dtable[in[cc+1]] Shr 4)
  336. If out.Length > (bc+1) Then p[1] = ((dtable[in[cc+1]] & $F) Shl 4) | ((dtable[in[cc+2]]&$3C) Shr 2)
  337. If out.Length > (bc+2) Then p[2] = ((dtable[in[cc+2]] & $3) Shl 6) | dtable[in[cc+3]]
  338. bc :+ 3
  339. p :+ 3
  340. Next
  341. Return out
  342. End Function
  343.  
  344. ' Code by EdzUp/Yan (?)...
  345.  
  346. Function SHA1:String(in$)
  347.  
  348. Function Rol(val, shift)
  349. Return (val Shl shift) | (val Shr (32 - shift))
  350. End Function
  351.  
  352. Local h0:Long = $67452301
  353. Local h1:Long = $EFCDAB89
  354. Local h2:Long = $98BADCFE
  355. Local h3:Long = $10325476
  356. Local h4:Long = $C3D2E1F0
  357. Local a:Long = 0
  358. Local b:Long = 0
  359. Local c:Long = 0
  360. Local d:Long = 0
  361. Local e:Long = 0
  362. Local i:Long = 0
  363. Local f:Long = 0
  364. Local t:Long = 0
  365.  
  366. Local intCount:Long = (((in$.length + 8) Shr 6) + 1) Shl 4
  367. Local data:Long[intCount]
  368.  
  369. For c=0 Until in$.length
  370. data[c Shr 2] = (data[c Shr 2] Shl 8) | (in$[c] & $FF)
  371. Next
  372.  
  373. data[in$.length Shr 2] = ((data[in$.length Shr 2] Shl 8) | $80) Shl ((3 - (in$.length & 3)) Shl 3)
  374. data[data.length - 2] = (Long(in$.length) * 8) Shr 32
  375. data[data.length - 1] = (Long(in$.length) * 8) & $FFFFFFFF
  376.  
  377. For Local chunkStart:Long=0 Until intCount Step 16
  378.  
  379. a = h0
  380. b = h1
  381. c = h2
  382. d = h3
  383. e = h4
  384.  
  385. Local w:Long[] = data[chunkStart..chunkStart + 16]
  386. w = w[..80]
  387.  
  388. For i=16 To 79
  389. w[i] = Rol(w[i - 3] ~ w[i - 8] ~ w[i - 14] ~ w[i - 16], 1)
  390. Next
  391.  
  392. For i=0 To 19
  393. t = Rol(a, 5) + (d ~ (b & (c ~ d))) + e + $5A827999 + w[i]
  394.  
  395. e = d ; d = c
  396. c = Rol(b, 30)
  397. b = a ; a = t
  398. Next
  399.  
  400. For i=20 To 39
  401. t = Rol(a, 5) + (b ~ c ~ d) + e + $6ED9EBA1 + w[i]
  402.  
  403. e = d ; d = c
  404. c = Rol(b, 30)
  405. b = a ; a = t
  406. Next
  407.  
  408. For i = 40 To 59
  409. t = Rol(a, 5) + ((b & c) | (d & (b | c))) + e + $8F1BBCDC + w[i]
  410.  
  411. e = d ; d = c
  412. c = Rol(b, 30)
  413. b = a ; a = t
  414. Next
  415.  
  416. For i = 60 To 79
  417. t = Rol(a, 5) + (b ~ c ~ d) + e + $CA62C1D6 + w[i]
  418.  
  419. e = d ; d = c
  420. c = Rol(b, 30)
  421. b = a ; a = t
  422. Next
  423.  
  424. h0 :+ a ; h1 :+ b ; h2 :+ c
  425. h3 :+ d ; h4 :+ e
  426.  
  427. Next
  428.  
  429. Return (Hex(h0) + Hex(h1) + Hex(h2) + Hex(h3) + Hex(h4)).ToLower()
  430.  
  431. End Function
Advertisement
Add Comment
Please, Sign In to add comment