tcpCommServer.vb 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407
  1. Imports System
  2. Imports System.Threading
  3. Imports System.Net
  4. Imports System.Net.Sockets
  5. Imports System.IO
  6. Imports System.Reflection
  7. Imports System.Runtime.InteropServices
  8. Imports System.Collections.Concurrent
  9. Public Class TcpCommServer
  10. Public errMsg As String
  11. ' Define the callback delegate type
  12. Public Delegate Sub ServerCallbackDelegate(ByVal bytes() As Byte, ByVal sessionID As Int32, ByVal dataChannel As Byte)
  13. Private Delegate Sub SendQueueDelegate(ByVal bytes() As Byte, ByVal dataChannel As Byte, ByVal sessionID As Int32)
  14. ' Create Delegate object
  15. Public ServerCallbackObject As ServerCallbackDelegate
  16. Private SendCallback As SendQueueDelegate
  17. Private Listener As TcpListener
  18. Private continue_running As Boolean = False
  19. Private blockSize As UInt16
  20. Private Port As Integer
  21. Private localAddr As IPAddress
  22. Private Mbps As UInt32
  23. Public IsRunning As Boolean = False
  24. Private receiveBuffer As BytesReceivedQueue
  25. Private sendBuffer As BytesSentQueue
  26. Public Class clsTimingController
  27. Public Delegate Function EvaluateExitCondition() As Boolean
  28. Public Function Wait(ByVal duration As TimeSpan, ByRef exitEarlyCondition1 As Boolean, ByRef exitEarlyCondition2 As Boolean,
  29. Optional ByVal exitWhenConditionIs As Boolean = True,
  30. Optional ByVal exitEarlyOnlyWhenBothConditionsAreMet As Boolean = True,
  31. Optional ByVal sleepWhileWaiting As Boolean = True) As Boolean
  32. Dim timeOut As Date = Now + duration
  33. Dim onTheUIThread As Boolean = DetectUIThread()
  34. While Now < timeOut
  35. If exitEarlyOnlyWhenBothConditionsAreMet then
  36. If exitWhenConditionIs = exitEarlyCondition1 And
  37. exitWhenConditionIs = exitEarlyCondition2 Then Return False
  38. Else
  39. If exitWhenConditionIs = exitEarlyCondition1 Or
  40. exitWhenConditionIs = exitEarlyCondition2 Then Return False
  41. End If
  42. If onTheUIThread Then
  43. If sleepWhileWaiting Then System.Windows.Forms.Application.DoEvents()
  44. Else
  45. If sleepWhileWaiting Then Threading.Thread.Sleep(1)
  46. End If
  47. End While
  48. Return True
  49. End Function
  50. Public Function Wait(ByVal duration As TimeSpan, ByRef exitCondition As EvaluateExitCondition,
  51. Optional ByVal exitWhenConditionIs As Boolean = True,
  52. Optional ByVal sleepWhileWaiting As Boolean = True) As Boolean
  53. Dim timeOut As Date = Now + duration
  54. Dim onTheUIThread As Boolean = DetectUIThread()
  55. Dim exitEarly As Boolean = False
  56. While Now < timeOut
  57. If exitCondition() Then Return False
  58. If onTheUIThread Then
  59. If sleepWhileWaiting Then System.Windows.Forms.Application.DoEvents()
  60. Else
  61. If sleepWhileWaiting Then Threading.Thread.Sleep(1)
  62. End If
  63. End While
  64. Return True
  65. End Function
  66. Public Function DetectUIThread() As Boolean
  67. Return System.Windows.Forms.Application.MessageLoop
  68. End Function
  69. End Class
  70. Private Class BytesSentQueue
  71. Private Class message
  72. Public bytes() As Byte
  73. Public dataChannel As Byte
  74. Public sessionID As Int32
  75. End Class
  76. Private spinning As Boolean
  77. Private addedMore As Boolean
  78. Private throttle As Boolean
  79. Private paused As Boolean
  80. Private queueSize As Int32
  81. Private running As Boolean
  82. Private sendQueue As New ConcurrentQueue(Of message)
  83. Private thisTcpCommServer As TcpCommServer
  84. Private timingControl As New clsTimingController
  85. Sub New(ByRef _tcpCommServer As TcpCommServer, Optional ByVal _queueSize As Int32 = 100)
  86. thisTcpCommServer = _tcpCommServer
  87. queueSize = _queueSize
  88. spinning = False
  89. addedMore = False
  90. running = True
  91. paused = False
  92. throttle = False
  93. Dim st As New Thread(AddressOf sendThrottle)
  94. st.Start
  95. End Sub
  96. Public Sub Close()
  97. running = False
  98. End Sub
  99. Public Sub PauseSending()
  100. paused = True
  101. End Sub
  102. Public Sub ResumeSending()
  103. paused = False
  104. End Sub
  105. Public Function IsPaused() As Boolean
  106. Return paused
  107. End Function
  108. Private Sub sendThrottle()
  109. While running
  110. If sendQueue.Count > queueSize then
  111. throttle = True
  112. Else
  113. throttle = False
  114. End If
  115. Thread.Sleep(20)
  116. End While
  117. throttle = False
  118. End Sub
  119. Public Sub AddToQueue(ByVal bytes() As Byte, ByVal dataChannel As Byte, ByRef sessionID As Int32)
  120. ' Throttle the send queue. If we don't do this, then
  121. ' The user may accidently use up all the available memory
  122. ' queueing sends while waiting for the machine on the other
  123. ' end to process the data sent.
  124. 'If throttle then timingControl.Wait(New TimeSpan(0, 0, 0, 60), throttle, throttle, False, False)
  125. ' Did we dump out of the loop because we're being closed?
  126. If Not running then Exit Sub
  127. Dim msg As New message
  128. Dim theseBytes(bytes.Length - 1) As Byte
  129. Array.Copy(bytes, theseBytes, bytes.Length)
  130. msg.dataChannel = dataChannel
  131. msg.sessionId = sessionID
  132. msg.bytes = theseBytes
  133. sendQueue.Enqueue(msg)
  134. If Not spinning Then
  135. Dim bgThread As New Thread(AddressOf DoSafeSend)
  136. bgThread.Name = "TcpServerSafeSendBackgroundThread"
  137. bgThread.Start()
  138. spinning = True
  139. addedMore = False
  140. Else
  141. addedMore = True
  142. End If
  143. End Sub
  144. Private Sub DoSafeSend()
  145. If paused and running then
  146. Dim timout As Date = Now.AddMilliseconds(200)
  147. While paused and running
  148. If timout < Now then Thread.Sleep(0)
  149. End While
  150. End If
  151. Dim msg As message = Nothing
  152. While spinning
  153. If sendQueue.TryPeek(msg) Then
  154. sendQueue.TryDequeue(msg)
  155. thisTcpCommServer.SendBytes(msg.bytes, msg.dataChannel, msg.sessionID)
  156. msg = Nothing
  157. Else
  158. Dim timer As Date = Now
  159. While timer.AddMilliseconds(200) < Now
  160. If sendQueue.TryPeek(msg) Then Exit While
  161. End While
  162. If Not sendQueue.TryPeek(msg) Then
  163. spinning = False
  164. Exit Sub
  165. End If
  166. End If
  167. End While
  168. End Sub
  169. End Class
  170. Private Class BytesReceivedQueue
  171. Private Class message
  172. Public bytes() As Byte
  173. Public dataChannel As Byte
  174. Public sessionId As Int32
  175. End Class
  176. Private spinning As Boolean = False
  177. Private addedMore As Boolean = False
  178. Private queueSize As Int32
  179. Private receiveQueue As New ConcurrentQueue(Of message)
  180. Private CallbackObject As ServerCallbackDelegate
  181. Sub New(ByRef _CallbackObject As ServerCallbackDelegate, Optional ByVal _queueSize As Int32 = 100)
  182. CallbackObject = _CallbackObject
  183. queueSize = _queueSize
  184. End Sub
  185. Public Sub AddToQueue(ByVal bytes() As Byte, ByVal dataChannel As Byte, ByRef session As SessionCommunications)
  186. Dim msg As New message
  187. Dim theseBytes(bytes.Length - 1) As Byte
  188. Array.Copy(bytes, theseBytes, bytes.Length)
  189. msg.dataChannel = dataChannel
  190. msg.sessionId = session.sessionID
  191. msg.bytes = theseBytes
  192. receiveQueue.Enqueue(msg)
  193. If Not spinning Then
  194. Dim bgThread As New Thread(AddressOf DoSafeReceive)
  195. bgThread.Start(session)
  196. spinning = True
  197. addedMore = False
  198. Else
  199. addedMore = True
  200. End If
  201. End Sub
  202. Private Sub DoSafeReceive(ByVal _session As Object)
  203. Dim msg As message = Nothing
  204. Dim session As SessionCommunications = CType(_session, SessionCommunications)
  205. While spinning
  206. If receiveQueue.TryPeek(msg) Then
  207. receiveQueue.TryDequeue(msg)
  208. CallbackObject(msg.bytes, msg.sessionId, msg.dataChannel)
  209. msg = Nothing
  210. Else
  211. Dim timer As Date = Now
  212. While timer.AddMilliseconds(200) < Now
  213. If receiveQueue.TryPeek(msg) Then Exit While
  214. End While
  215. If Not receiveQueue.TryPeek(msg) Then
  216. spinning = False
  217. Exit Sub
  218. End If
  219. End If
  220. End While
  221. End Sub
  222. End Class
  223. Public SessionCollection As New ArrayList
  224. Private Class SessionCommunications
  225. Public UserBytesToBeSentAvailable As Boolean = False
  226. Public UserBytesToBeSent As New MemoryStream
  227. Public UserOutputChannel As Byte
  228. Public SystemBytesToBeSentAvailable As Boolean = False
  229. Public SystemBytesToBeSent() As Byte
  230. Public SystemOutputChannel As Byte
  231. Public theClient As TcpClient
  232. Public IsRunning As Boolean = False
  233. Public remoteIpAddress As System.Net.IPAddress
  234. Public bytesRecieved() As Byte
  235. Public sessionID As Int32
  236. Public disConnect As Boolean = False
  237. Public bytesSentThisSecond As Int32 = 0
  238. Public bytesRecievedThisSecond As Int32 = 0
  239. Public fileBytesRecieved As Int64 = 0
  240. Public filebytesSent As Int64 = 0
  241. Public SendingFile As Boolean = False
  242. Public FileBeingSentPath As String
  243. Public IncomingFileSize As Int64
  244. Public IncomingFileName As String
  245. Public ReceivingFile As Boolean = False
  246. Public sendPacketSize As Boolean = False
  247. Public fileReader As FileStream
  248. Public fileWriter As clsAsyncUnbuffWriter
  249. Public ReceivedFilesFolder As String = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) & "\ServerReceivedFiles"
  250. Public userName As String
  251. Public password As String
  252. Public paused As Boolean
  253. Public pauseSent As Boolean
  254. Public Sub New(ByVal _theClient As TcpClient, ByVal _sessionID As Int32)
  255. theClient = _theClient
  256. sessionID = _sessionID
  257. paused = False
  258. pauseSent = False
  259. End Sub
  260. Public Sub Close()
  261. disConnect = True
  262. Try
  263. theClient.Client.Blocking = False
  264. theClient.Client.Close()
  265. Catch ex As Exception
  266. IsRunning = False
  267. End Try
  268. End Sub
  269. End Class
  270. Private Function StrToByteArray(ByVal text As String) As Byte()
  271. Dim encoding As New System.Text.UTF8Encoding()
  272. StrToByteArray = encoding.GetBytes(text)
  273. End Function
  274. Private Function BytesToString(ByVal data() As Byte) As String
  275. Dim enc As New System.Text.UTF8Encoding()
  276. BytesToString = enc.GetString(data)
  277. End Function
  278. ' CallbackForm must implement an UpdateUI Sub.
  279. Public Sub New(ByVal callbackMethod As ServerCallbackDelegate, Optional ByVal _throttledBytesPerSecond As UInt32 = 9000000)
  280. Mbps = _throttledBytesPerSecond
  281. 'receiveBuffer = New BytesReceivedQueue(callbackMethod)
  282. 'sendBuffer = New BytesSentQueue(me)
  283. ' BlockSize should be 62500 or 63100, depending on requested speed.
  284. ' Excellent performance, and works great with throttling.
  285. Dim _blockSize As UInt16
  286. ' Get corrected blocksize for throttling.
  287. If Mbps < 300000 Then
  288. If Mbps > 16000 Then
  289. blockSize = 4000
  290. Else
  291. blockSize = CUShort((Mbps / 4))
  292. End If
  293. ElseIf Mbps > 300000 And Mbps < 500000 Then
  294. blockSize = 16000
  295. ElseIf Mbps > 500000 And Mbps < 1000000 Then
  296. blockSize = 32000
  297. Else
  298. Dim count As UInt32 = 0
  299. Dim aFourth As Decimal = 0
  300. If Mbps > 25000000 Then
  301. _blockSize = 63100
  302. Else
  303. _blockSize = 62500
  304. End If
  305. aFourth = CDec(Mbps / 4)
  306. Do
  307. count += _blockSize
  308. If (count + _blockSize) > aFourth Then
  309. Mbps = CUInt(count * 4)
  310. blockSize = _blockSize
  311. Exit Do
  312. End If
  313. Loop
  314. End If
  315. ' Initialize the delegate object to point to the user's callback method.
  316. ServerCallbackObject = callbackMethod
  317. End Sub
  318. Public Sub ThrottleNetworkBps(ByVal bytesPerSecond As UInteger)
  319. ' Default value is 9000000 Mbps. Ok throughput, and
  320. ' good performance for the server (low CPU usage).
  321. Mbps = bytesPerSecond
  322. End Sub
  323. Public Sub Start(ByVal prt As Integer)
  324. receiveBuffer = New BytesReceivedQueue(ServerCallbackObject)
  325. sendBuffer = New BytesSentQueue(me)
  326. Port = prt
  327. localAddr = GetLocalIpAddress()
  328. continue_running = True
  329. IsRunning = True
  330. Dim listenerThread As New Thread(AddressOf theListener)
  331. listenerThread.Name = "Server Listener Thread"
  332. listenerThread.Start()
  333. End Sub
  334. Public Sub StopRunning()
  335. Dim theresSillOneRunning As Boolean = True
  336. continue_running = False
  337. While theresSillOneRunning
  338. Try
  339. For Each item As SessionCommunications In SessionCollection
  340. item.Close()
  341. Next
  342. Catch ex As Exception
  343. End Try
  344. Try
  345. For Each item As SessionCommunications In SessionCollection
  346. If item.IsRunning Then Exit Try
  347. Next
  348. theresSillOneRunning = False
  349. Catch ex As Exception
  350. End Try
  351. End While
  352. Try
  353. Listener.Stop()
  354. Catch ex As Exception
  355. End Try
  356. IsRunning = False
  357. sendBuffer.Close
  358. End Sub
  359. Private Function GetLocalIpAddress() As System.Net.IPAddress
  360. Dim strHostName As String
  361. Dim addresses() As System.Net.IPAddress
  362. strHostName = System.Net.Dns.GetHostName()
  363. addresses = System.Net.Dns.GetHostAddresses(strHostName)
  364. ' Find an IpV4 address
  365. For Each address As System.Net.IPAddress In addresses
  366. ' Return the first IpV4 IP Address we find in the list.
  367. If address.AddressFamily = AddressFamily.InterNetwork then
  368. Return address
  369. End If
  370. Next
  371. ' No IpV4 address? Return the loopback address.
  372. Return System.Net.IPAddress.Loopback
  373. End Function
  374. Public Function GetBlocksize() As UInt16
  375. Return blockSize
  376. End Function
  377. Public Function GetFile(ByVal _path As String, ByVal sessionID As Int32) As Boolean
  378. Dim foundSession As Boolean = False
  379. GetFile = True
  380. ' Find the session we want to talk to and send it a Get File Request
  381. For Each session As SessionCommunications In SessionCollection
  382. If session.sessionID = sessionID Then
  383. ' we found it.
  384. foundSession = True
  385. Do
  386. If Not session.UserBytesToBeSentAvailable Then
  387. SyncLock session.UserBytesToBeSent
  388. session.UserBytesToBeSent.Close()
  389. session.UserBytesToBeSent = Nothing
  390. session.UserBytesToBeSent = New MemoryStream(StrToByteArray("GFR:" & _path))
  391. session.UserOutputChannel = 254 ' Text messages / commands on channel 254
  392. session.UserBytesToBeSentAvailable = True
  393. End SyncLock
  394. Exit Do
  395. End If
  396. If Not session.IsRunning Then Exit Do
  397. Thread.Sleep(0)
  398. Loop
  399. End If
  400. Next
  401. If Not foundSession Then Return False
  402. End Function
  403. Public Function SendFile(ByVal _path As String, ByVal sessionID As Int32) As Boolean
  404. Dim foundSession As Boolean = False
  405. SendFile = True
  406. ' Find the session we want to talk to and send it a Send File Request
  407. For Each session As SessionCommunications In SessionCollection
  408. If session.sessionID = sessionID Then
  409. ' we found it.
  410. foundSession = True
  411. Do
  412. If Not session.UserBytesToBeSentAvailable Then
  413. SyncLock session.UserBytesToBeSent
  414. session.UserBytesToBeSent.Close()
  415. session.UserBytesToBeSent = Nothing
  416. session.UserBytesToBeSent = New MemoryStream(StrToByteArray("SFR:" & _path))
  417. session.UserOutputChannel = 254 ' Text messages / commands on channel 254
  418. session.UserBytesToBeSentAvailable = True
  419. End SyncLock
  420. Exit Do
  421. End If
  422. If Not session.IsRunning Then Exit Do
  423. Thread.Sleep(0)
  424. Loop
  425. End If
  426. Next
  427. If Not foundSession Then Return False
  428. End Function
  429. Private Function SendTheBytes(ByVal bytes() As Byte, ByVal channel As Byte, ByVal sessionID As Int32) As Boolean
  430. Dim foundSession As Boolean = False
  431. SendTheBytes = True
  432. If channel = 0 Or channel > 250 Then
  433. MsgBox("Data can not be sent using channel numbers less then 1 or greater then 250.", MsgBoxStyle.Critical, "TCP_Server")
  434. Exit Function
  435. End If
  436. If sessionID > -1 Then
  437. ' Find the session we want to talk to and send it the message
  438. For Each session As SessionCommunications In SessionCollection
  439. If session.sessionID = sessionID Then
  440. ' we found it.
  441. foundSession = True
  442. Do
  443. If Not session.UserBytesToBeSentAvailable Then
  444. SyncLock session.UserBytesToBeSent
  445. session.UserBytesToBeSent.Close()
  446. session.UserBytesToBeSent = Nothing
  447. session.UserBytesToBeSent = New MemoryStream(bytes)
  448. session.UserOutputChannel = channel
  449. session.UserBytesToBeSentAvailable = True
  450. End SyncLock
  451. Exit Do
  452. End If
  453. If Not session.IsRunning Then Exit Do
  454. Thread.Sleep(0)
  455. Loop
  456. End If
  457. Next
  458. If Not foundSession Then Return False
  459. ElseIf sessionID = -1 Then
  460. ' Send our message to everyone connected
  461. For Each session As SessionCommunications In SessionCollection
  462. If session.IsRunning Then
  463. Do
  464. If Not session.UserBytesToBeSentAvailable Then
  465. SyncLock session.UserBytesToBeSent
  466. session.UserBytesToBeSent.Close()
  467. session.UserBytesToBeSent = Nothing
  468. session.UserBytesToBeSent = New MemoryStream(bytes)
  469. session.UserOutputChannel = channel
  470. session.UserBytesToBeSentAvailable = True
  471. End SyncLock
  472. Exit Do
  473. End If
  474. If Not session.IsRunning Then Exit Do
  475. Thread.Sleep(0)
  476. Loop
  477. End If
  478. Next
  479. Else
  480. Return False
  481. End If
  482. End Function
  483. Public Function SendBytes(ByVal bytes() As Byte, Optional ByVal channel As Byte = 1, Optional ByVal sessionID As Int32 = -1) As Boolean
  484. 'If Thread.CurrentThread.Name = "TcpServerSafeSendBackgroundThread" then
  485. SendTheBytes(bytes, channel, sessionID)
  486. 'Else
  487. ' sendBuffer.AddToQueue(bytes, channel, sessionID)
  488. 'End If
  489. End Function
  490. Private Function RcvBytes(ByVal data() As Byte, ByRef session As SessionCommunications, Optional ByVal dataChannel As Byte = 1) As Boolean
  491. ' dataType: >0 = data channel, > 250 = internal messages. 0 is an invalid channel number (it's the puck)
  492. If dataChannel < 1 Then
  493. RcvBytes = False
  494. Exit Function
  495. End If
  496. Try
  497. ' Check to see if our app is closing
  498. If Not continue_running Then Exit Function
  499. receiveBuffer.AddToQueue(data, dataChannel, session)
  500. Catch ex As Exception
  501. RcvBytes = False
  502. ' An unexpected error.
  503. Debug.WriteLine("Unexpected error in server\RcvBytes: " & ex.Message)
  504. End Try
  505. End Function
  506. Private Function SendExternalSystemMessage(ByVal message As String, ByVal session As SessionCommunications) As Boolean
  507. session.SystemBytesToBeSent = StrToByteArray(message)
  508. session.SystemOutputChannel = 254 ' Text messages / commands on channel 254
  509. session.SystemBytesToBeSentAvailable = True
  510. End Function
  511. Private Function CheckSessionPermissions(ByVal session As SessionCommunications, ByVal cmd As String) As Boolean
  512. ' Your security code here...
  513. Return True
  514. End Function
  515. Private Function BeginFileSend(ByVal _path As String, ByVal session As SessionCommunications, ByVal fileLength As Long) As Boolean
  516. Try
  517. session.fileReader = New FileStream(_path, FileMode.Open, FileAccess.Read, FileShare.None, clsAsyncUnbuffWriter.GetPageSize)
  518. session.SendingFile = True
  519. BeginFileSend = True
  520. Catch ex As Exception
  521. BeginFileSend = False
  522. _path = ex.Message
  523. session.SendingFile = False
  524. End Try
  525. Try
  526. If Not BeginFileSend Then session.fileReader.Close()
  527. Catch ex As Exception
  528. End Try
  529. End Function
  530. Private Sub GetMoreFileBytesIfAvailable(ByVal session As SessionCommunications)
  531. Dim bytesRead As Int32 = 0
  532. If session.SendingFile And Not session.SystemBytesToBeSentAvailable Then
  533. Try
  534. If session.SystemBytesToBeSent.Length <> blockSize Then ReDim session.SystemBytesToBeSent(blockSize - 1)
  535. bytesRead = session.fileReader.Read(session.SystemBytesToBeSent, 0, blockSize)
  536. If bytesRead <> blockSize Then ReDim Preserve session.SystemBytesToBeSent(bytesRead - 1)
  537. If bytesRead > 0 Then
  538. session.SystemOutputChannel = 253 ' File transfer from server to client
  539. session.SystemBytesToBeSentAvailable = True
  540. Else
  541. ReDim session.SystemBytesToBeSent(blockSize - 1)
  542. SendExternalSystemMessage("->Done", session) ' Send the client a completion notice.
  543. session.SendingFile = False
  544. ' Clean up
  545. session.fileReader.Close()
  546. session.fileReader = Nothing
  547. GC.GetTotalMemory(True)
  548. End If
  549. Catch ex As Exception
  550. SendExternalSystemMessage("ERR: " & ex.Message, session)
  551. ' We're finished.
  552. ReDim session.SystemBytesToBeSent(blockSize - 1)
  553. session.SendingFile = False
  554. session.fileReader.Close()
  555. End Try
  556. End If
  557. End Sub
  558. Private Function GetFilenameFromPath(ByRef filePath As String) As String
  559. Dim filePathParts() As String
  560. If filePath.Trim = "" Then Return ""
  561. Try
  562. filePathParts = Split(filePath, "\")
  563. GetFilenameFromPath = filePathParts(filePathParts.Length - 1)
  564. Catch ex As Exception
  565. filePath = ex.Message
  566. Return ""
  567. End Try
  568. End Function
  569. Private Function CreateFolders(ByVal _path As String) As Boolean
  570. CreateFolders = True
  571. Dim parts() As String
  572. Dim path As String = ""
  573. Dim count As Int32
  574. parts = Split(_path, "\")
  575. path = parts(0)
  576. For count = 1 To parts.Length - 2
  577. path += "\" & parts(count)
  578. Try
  579. If Not Directory.Exists(path) Then
  580. Directory.CreateDirectory(path)
  581. End If
  582. Catch ex As Exception
  583. End Try
  584. Next
  585. End Function
  586. Private Function BeginToReceiveAFile(ByVal _path As String, ByVal session As SessionCommunications) As Boolean
  587. Dim readBuffer As Int32 = 0
  588. session.ReceivingFile = True
  589. BeginToReceiveAFile = True
  590. session.fileBytesRecieved = 0
  591. Try
  592. CreateFolders(_path) ' Just a 256k write buffer for the server. Let's try to avoid memory problems...
  593. session.fileWriter = New clsAsyncUnbuffWriter(_path, True, 1024 * 256, session.IncomingFileSize)
  594. Catch ex As Exception
  595. _path = ex.Message
  596. session.ReceivingFile = False
  597. End Try
  598. If Not session.ReceivingFile Then
  599. Try
  600. session.fileWriter.Close()
  601. Catch ex As Exception
  602. End Try
  603. Return False
  604. End If
  605. End Function
  606. Private Function HandleIncomingFileBytes(ByRef bytes() As Byte, ByVal session As SessionCommunications) As Boolean
  607. Try
  608. session.fileWriter.Write(bytes, bytes.Length)
  609. HandleIncomingFileBytes = True
  610. Catch ex As Exception
  611. HandleIncomingFileBytes = False
  612. End Try
  613. End Function
  614. Private Sub FinishReceivingTheFile(ByVal session As SessionCommunications)
  615. Try
  616. session.fileWriter.Close()
  617. session.fileWriter = Nothing
  618. session.ReceivingFile = False
  619. Catch ex As Exception
  620. session.ReceivingFile = False
  621. End Try
  622. End Sub
  623. Private Sub HandleIncomingSystemMessages(ByVal bytes() As Byte, ByVal channel As Byte, ByVal session As SessionCommunications)
  624. If channel = 254 Then ' Text commands / messages passed between server and client
  625. Dim message As String = BytesToString(bytes)
  626. Dim filePath As String
  627. Dim tmp As String = ""
  628. ' Get File Request: The client wants us to send them a file.
  629. If message.Length > 4 Then tmp = message.Substring(0, 4)
  630. If tmp = "GFR:" Then
  631. ' Get file path...
  632. filePath = message.Substring(4, message.Length - 4)
  633. ' Does it exist?
  634. If File.Exists(filePath) Then
  635. ' Do they have permission to get this file?
  636. If CheckSessionPermissions(session, "GFR") Then
  637. ' Are we already busy sending them a file?
  638. If Not session.SendingFile Then
  639. Dim _theFilesInfo As New FileInfo(filePath)
  640. If BeginFileSend(filePath, session, _theFilesInfo.Length) Then
  641. ' Send only the file NAME. It will have a different path on the other side.
  642. SendExternalSystemMessage("Sending:" & GetFilenameFromPath(filePath) & _
  643. ":" & _theFilesInfo.Length, session)
  644. Else
  645. ' FilePath contains the error message.
  646. SendExternalSystemMessage("ERR: " & filePath, session)
  647. End If
  648. Else
  649. ' There's already a GFR in progress.
  650. SendExternalSystemMessage("ERR: File: ''" & _
  651. session.FileBeingSentPath & _
  652. "'' is still in progress. Only one file " & _
  653. "may be transfered (from server to client) at a time.", session)
  654. End If
  655. Else
  656. ' This user doesn't have rights to "get" this file. Send an error.
  657. SendExternalSystemMessage("ERR: You do not have permission to receive files. Access Denied.", session)
  658. End If
  659. Else
  660. ' File doesn't exist. Send an error.
  661. SendExternalSystemMessage("ERR: The requested file can not be found by the server.", session)
  662. End If
  663. End If
  664. ' We're being informed that we will be receiving a file:
  665. If message.Length > 7 Then tmp = message.Substring(0, 8)
  666. If tmp = "Sending:" Then
  667. ' Strip away the headder...
  668. Dim msgParts() As String = Split(message, ":")
  669. session.IncomingFileSize = Convert.ToInt64(msgParts(2))
  670. session.IncomingFileName = msgParts(1)
  671. tmp = session.ReceivedFilesFolder & "\" & session.IncomingFileName
  672. SystemMessage("Receiving file: " & session.IncomingFileName)
  673. If Not BeginToReceiveAFile(tmp, session) Then
  674. SystemMessage("ERR: " & tmp)
  675. SendExternalSystemMessage("Abort->", session)
  676. End If
  677. End If
  678. If message = "<-Done" Then
  679. FinishReceivingTheFile(session)
  680. SystemMessage("<-Done")
  681. End If
  682. ' We've been notified that no file data will be forthcoming.
  683. If message = "Abort<-" Then
  684. WrapUpIncomingFile(session)
  685. SystemMessage("<-Aborted.")
  686. SendExternalSystemMessage("<-Aborted.", session)
  687. End If
  688. ' Send File Request: The client wants to send us a file.
  689. If message.Length > 4 Then tmp = message.Substring(0, 4)
  690. If tmp = "SFR:" Then
  691. If CheckSessionPermissions(session, "SFR") Then
  692. Dim parts() As String
  693. parts = Split(message, "SFR:")
  694. SendExternalSystemMessage("GFR:" & parts(1), session)
  695. Else
  696. ' This user doesn't have rights to send us a file. Send an error.
  697. SendExternalSystemMessage("ERR: You do not have permission to send files. Access Denied.", session)
  698. End If
  699. End If
  700. If message.Length > 4 Then tmp = message.Substring(0, 4)
  701. If tmp = "GDR:" Then ' Get Directory Request
  702. ' Send each file in the directory and all subdirectories.
  703. ' To be implemented in the future.
  704. End If
  705. If message.Length > 4 Then tmp = message.Substring(0, 4)
  706. If tmp = "ERR:" Then ' The client has sent us an error message.
  707. ' Pass it on up to the user.
  708. SystemMessage(message)
  709. End If
  710. ' New queue throttling code
  711. If message = "pause" Then
  712. session.paused = True
  713. End If
  714. If message = "resume" Then
  715. session.paused = False
  716. End If
  717. If message = "Abort->" Then
  718. Try
  719. session.SendingFile = False
  720. ReDim session.SystemBytesToBeSent(blockSize - 1)
  721. SendExternalSystemMessage("->Aborted.", session)
  722. SystemMessage("->Aborted.")
  723. session.fileReader.Close()
  724. Catch ex As Exception
  725. End Try
  726. End If
  727. ElseIf channel = 253 Then ' File transfer from server to client
  728. ElseIf channel = 252 Then ' File transfer from client to server
  729. Try
  730. If session.ReceivingFile Then
  731. HandleIncomingFileBytes(bytes, session)
  732. session.fileBytesRecieved += bytes.Length
  733. End If
  734. Catch ex As Exception
  735. End Try
  736. ElseIf channel = 251 Then ' reserved.
  737. End If
  738. End Sub
  739. Private Function HandleOutgoingInternalSystemMessage(ByVal Stream As NetworkStream, _
  740. ByVal session As SessionCommunications) As Boolean
  741. Dim tmp(1) As Byte
  742. Dim _size As UShort
  743. 'Static OurTurn As Boolean = False
  744. HandleOutgoingInternalSystemMessage = False
  745. ' Create a one time outgoing system message to syncronize packet size.
  746. If Not session.sendPacketSize Then
  747. SendExternalSystemMessage("blocksize:" & blockSize.ToString, session)
  748. session.sendPacketSize = True
  749. End If
  750. GetMoreFileBytesIfAvailable(session)
  751. ' Handle outgoing system stuff here
  752. If session.SystemBytesToBeSentAvailable = True Then
  753. HandleOutgoingInternalSystemMessage = True
  754. If session.SystemBytesToBeSent.Length > blockSize Then
  755. ' Send Channel
  756. tmp(0) = session.SystemOutputChannel
  757. Stream.Write(tmp, 0, 1)
  758. ' Send packet size
  759. _size = blockSize
  760. tmp = BitConverter.GetBytes(_size)
  761. Stream.Write(tmp, 0, 2)
  762. ' Send packet
  763. Stream.Write(GetSome(session.SystemBytesToBeSent, blockSize, session.SystemBytesToBeSentAvailable, session), 0, _size)
  764. session.bytesSentThisSecond += 3 + blockSize
  765. Else
  766. ' Send Channel
  767. tmp(0) = session.SystemOutputChannel
  768. Stream.Write(tmp, 0, 1)
  769. ' Send packet size
  770. _size = convert.ToUInt16(session.SystemBytesToBeSent.Length)
  771. tmp = BitConverter.GetBytes(_size)
  772. Stream.Write(tmp, 0, 2)
  773. ' Send packet
  774. Stream.Write(session.SystemBytesToBeSent, 0, _size)
  775. session.bytesSentThisSecond += 3 + _size
  776. session.SystemBytesToBeSentAvailable = False
  777. End If
  778. End If
  779. End Function
  780. Private Function HandleOutgoingUserData(ByVal Stream As NetworkStream, ByVal session As SessionCommunications) As Boolean
  781. Dim tmp(1) As Byte
  782. Dim _size As UShort
  783. Dim notify As Boolean = False
  784. Static packet(0) As Byte
  785. If session.UserBytesToBeSentAvailable = True Then
  786. SyncLock session.UserBytesToBeSent
  787. Try
  788. If (session.UserBytesToBeSent.Length - session.UserBytesToBeSent.Position) > blockSize Then
  789. ' Send Channel
  790. tmp(0) = session.UserOutputChannel
  791. Stream.Write(tmp, 0, 1)
  792. ' Send packet size
  793. _size = blockSize
  794. tmp = BitConverter.GetBytes(_size)
  795. Stream.Write(tmp, 0, 2)
  796. ' Send packet
  797. If packet.Length <> _size Then ReDim packet(_size - 1)
  798. session.UserBytesToBeSent.Read(packet, 0, _size)
  799. 'session.theClient.NoDelay = True
  800. Stream.Write(packet, 0, _size)
  801. session.bytesSentThisSecond += 3 + _size
  802. ' Check to see if we've sent it all...
  803. If session.UserBytesToBeSent.Length = session.UserBytesToBeSent.Position Then
  804. session.UserBytesToBeSentAvailable = False
  805. notify = True
  806. End If
  807. Else
  808. ' Send Channel
  809. tmp(0) = session.UserOutputChannel
  810. Stream.Write(tmp, 0, 1)
  811. ' Send packet size
  812. _size = Convert.ToUInt16(session.UserBytesToBeSent.Length - session.UserBytesToBeSent.Position)
  813. tmp = BitConverter.GetBytes(_size)
  814. Stream.Write(tmp, 0, 2)
  815. ' Send packet
  816. If packet.Length <> _size Then ReDim packet(_size - 1)
  817. session.UserBytesToBeSent.Read(packet, 0, _size)
  818. 'session.theClient.NoDelay = True
  819. Stream.Write(packet, 0, _size)
  820. session.bytesSentThisSecond += 3 + _size
  821. session.UserBytesToBeSentAvailable = False
  822. notify = True
  823. End If
  824. Catch ex As Exception
  825. ' Report error attempting to send user data.
  826. Debug.WriteLine("Unexpected error in TcpCommServer\HandleOutgoingUserData: " & ex.Message)
  827. End Try
  828. End SyncLock
  829. ' Notify the user that the packet has been sent.
  830. If notify Then SystemMessage("UBS:" & session.sessionID & ":" & session.UserOutputChannel)
  831. Return True
  832. Else
  833. Return False
  834. End If
  835. 'If session.UserBytesToBeSentAvailable = True Then
  836. ' If (session.UserBytesToBeSent.Length - session.UserBytesToBeSent.Position) > blockSize Then
  837. ' ' Send Channel
  838. ' tmp(0) = session.UserOutputChannel
  839. ' Stream.Write(tmp, 0, 1)
  840. ' ' Send packet size
  841. ' _size = blockSize
  842. ' tmp = BitConverter.GetBytes(_size)
  843. ' Stream.Write(tmp, 0, 2)
  844. ' ' Send packet
  845. ' If packet.Length <> _size Then ReDim packet(_size - 1)
  846. ' session.UserBytesToBeSent.Read(packet, 0, _size)
  847. ' Stream.Write(packet, 0, _size)
  848. ' session.bytesSentThisSecond += 3 + _size
  849. ' ' Check to see if we've sent it all...
  850. ' If session.UserBytesToBeSent.Length = session.UserBytesToBeSent.Position Then
  851. ' session.UserBytesToBeSentAvailable = False
  852. ' SystemMessage("UBS:" & session.sessionID & ":" & session.UserOutputChannel)
  853. ' End If
  854. ' Else
  855. ' ' Send Channel
  856. ' tmp(0) = session.UserOutputChannel
  857. ' Stream.Write(tmp, 0, 1)
  858. ' ' Send packet size
  859. ' _size = (session.UserBytesToBeSent.Length - session.UserBytesToBeSent.Position)
  860. ' tmp = BitConverter.GetBytes(_size)
  861. ' Stream.Write(tmp, 0, 2)
  862. ' ' Send packet
  863. ' If packet.Length <> _size Then ReDim packet(_size - 1)
  864. ' session.UserBytesToBeSent.Read(packet, 0, _size)
  865. ' Stream.Write(packet, 0, _size)
  866. ' session.bytesSentThisSecond += 3 + _size
  867. ' session.UserBytesToBeSentAvailable = False
  868. ' SystemMessage("UBS:" & session.sessionID & ":" & session.UserOutputChannel)
  869. ' End If
  870. ' Return True
  871. 'Else
  872. ' Return False
  873. 'End If
  874. End Function
  875. Private Function GetSome(ByRef bytes() As Byte, ByVal chunkToBreakOff As Integer, _
  876. ByRef bytesToBeSentAvailable As Boolean, ByVal session As SessionCommunications, _
  877. Optional ByVal theseAreUserBytes As Boolean = False) As Byte()
  878. Dim tmp(chunkToBreakOff - 1) As Byte
  879. Array.Copy(bytes, 0, tmp, 0, chunkToBreakOff)
  880. GetSome = tmp
  881. If bytes.Length = chunkToBreakOff Then
  882. bytesToBeSentAvailable = False
  883. If theseAreUserBytes Then SystemMessage("UBS:" & session.sessionID & ":" & session.UserOutputChannel)
  884. Else
  885. Dim tmp2(bytes.Length - chunkToBreakOff - 1) As Byte
  886. Array.Copy(bytes, chunkToBreakOff, tmp2, 0, bytes.Length - chunkToBreakOff)
  887. bytes = tmp2
  888. End If
  889. End Function
  890. Private Sub SystemMessage(ByVal MsgText As String)
  891. RcvBytes(StrToByteArray(MsgText), New SessionCommunications(New TcpClient, -1), 255)
  892. End Sub
  893. ' Check to see if our app is closing (set in FormClosing event)
  894. Private Function theServerIsStopping(ByVal Server As TcpClient, ByVal session As SessionCommunications) As Boolean
  895. Try
  896. If Not continue_running Or session.disConnect Then
  897. theServerIsStopping = True
  898. Else
  899. theServerIsStopping = False
  900. End If
  901. Catch ex As Exception
  902. ' An unexpected error.
  903. Debug.WriteLine("Unexpected error in server\theServerIsStopping: " & ex.Message)
  904. End Try
  905. End Function
  906. Private Sub theListener()
  907. ' Start listening
  908. SystemMessage("Listening...")
  909. Listener = New TcpListener(localAddr, Port)
  910. Listener.Start()
  911. StartAccept()
  912. End Sub
  913. Private Function StartAccept() As Boolean
  914. Try
  915. Listener.BeginAcceptTcpClient(AddressOf HandleAsyncConnection, Listener)
  916. Return True
  917. Catch ex As Exception
  918. Return False
  919. End Try
  920. End Function
  921. Private Sub HandleAsyncConnection(ByVal res As IAsyncResult)
  922. Static conID As Int32 = 0
  923. If Not StartAccept() Then Exit Sub
  924. conID += 1
  925. If conID > 2000000000 Then conID = 1 ' 2 billion connections before the ID cycles
  926. Dim client As TcpClient = Listener.EndAcceptTcpClient(res)
  927. SessionCollection.Insert(0, New SessionCommunications(client, conID))
  928. SystemMessage("Connected.")
  929. 'ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf Run), SessionCollection.Item(0))
  930. Dim newSession As New Thread(AddressOf Run)
  931. newSession.IsBackground = True
  932. newSession.Name = "Server Session #" & conID
  933. newSession.Start(SessionCollection.Item(0))
  934. End Sub
  935. Private Sub WrapUpIncomingFile(ByVal session As SessionCommunications)
  936. If session.ReceivingFile Then
  937. Try
  938. session.fileWriter.Close()
  939. session.fileWriter = Nothing
  940. GC.GetTotalMemory(True)
  941. Catch ex As Exception
  942. End Try
  943. Try
  944. File.Delete(session.ReceivedFilesFolder & "\" & session.IncomingFileName)
  945. Catch ex As Exception
  946. End Try
  947. End If
  948. End Sub
  949. Private Sub Run(ByVal _session As Object)
  950. Dim session As SessionCommunications = DirectCast(_session, SessionCommunications)
  951. Dim Server As TcpClient
  952. Dim Stream As NetworkStream
  953. Dim IpEndPoint As IPEndPoint
  954. Dim puck(1) As Byte : puck(0) = 0
  955. Dim theBuffer(blockSize - 1) As Byte
  956. Dim tmp(1) As Byte
  957. Dim dataChannel As Byte = 0
  958. Dim packetSize As UShort = 0
  959. Dim idleTimer, bandwidthTimer As Date
  960. Dim bytesread As Integer = 0
  961. Dim weHaveThePuck As Boolean = True
  962. Dim bandwidthUsedThisSecond As Int32 = 0
  963. Dim userOrSystemSwitcher As Integer = 0
  964. Try
  965. ' Create a local Server and Stream objects for clarity.
  966. Server = session.theClient
  967. Stream = Server.GetStream()
  968. Catch ex As Exception
  969. ' An unexpected error.
  970. Debug.WriteLine("Could not create local Server or Stream object in server. Message: " & ex.Message)
  971. Exit Sub
  972. End Try
  973. Try
  974. ' Get the remote machine's IP address.
  975. IpEndPoint = CType(Server.Client.RemoteEndPoint, Net.IPEndPoint)
  976. session.remoteIpAddress = IpEndPoint.Address
  977. ' Set the send and receive buffers to the maximum
  978. ' size allowable in this application...
  979. Server.Client.ReceiveBufferSize = 65535
  980. Server.Client.SendBufferSize = 65535
  981. ' no delay on partially filled packets...
  982. ' Send it all as fast as possible.
  983. Server.NoDelay = True
  984. ' Set the timers...
  985. idleTimer = Now
  986. bandwidthTimer = Now
  987. session.IsRunning = True
  988. ' Start the communication loop
  989. Do
  990. ' Check to see if our app is shutting down.
  991. If theServerIsStopping(Server, session) Then Exit Do
  992. ' Throttle network Mbps...
  993. bandwidthUsedThisSecond = session.bytesSentThisSecond + session.bytesRecievedThisSecond
  994. If bandwidthTimer.AddMilliseconds(250) >= Now And bandwidthUsedThisSecond >= (Mbps / 4) Then
  995. While bandwidthTimer.AddMilliseconds(250) > Now
  996. Thread.Sleep(0)
  997. End While
  998. End If
  999. If bandwidthTimer.AddMilliseconds(250) <= Now Then
  1000. bandwidthTimer = Now
  1001. session.bytesRecievedThisSecond = 0
  1002. session.bytesSentThisSecond = 0
  1003. bandwidthUsedThisSecond = 0
  1004. End If
  1005. ' Normal communications...
  1006. If weHaveThePuck Then
  1007. ' Send data if there is any to be sent...
  1008. userOrSystemSwitcher += 1
  1009. Select Case userOrSystemSwitcher
  1010. Case 1
  1011. If Not session.paused Then
  1012. If HandleOutgoingUserData(Stream, session) Then idleTimer = Now
  1013. End If
  1014. Case 2
  1015. If HandleOutgoingInternalSystemMessage(Stream, session) Then idleTimer = Now
  1016. End Select
  1017. If userOrSystemSwitcher > 1 Then userOrSystemSwitcher = 0
  1018. ' After sending out data, send the puck
  1019. Stream.Write(puck, 0, 1)
  1020. weHaveThePuck = False
  1021. End If
  1022. If theBuffer.Length < 2 Then ReDim theBuffer(1)
  1023. ' Read in the control byte.
  1024. Stream.Read(theBuffer, 0, 1)
  1025. dataChannel = theBuffer(0)
  1026. ' If it's just the puck (communictaion syncronization byte),
  1027. ' set weHaveThePuck true, record the byte read for throttling,
  1028. ' and that's all. dataChannel 0 is reserved for the puck.
  1029. If dataChannel = 0 Then
  1030. weHaveThePuck = True
  1031. session.bytesRecievedThisSecond += 1
  1032. Else
  1033. ' It's not the puck: It's an incoming packet.
  1034. ' Get the packet size:
  1035. tmp(0) = Convert.ToByte(Stream.ReadByte)
  1036. tmp(1) = Convert.ToByte(Stream.ReadByte)
  1037. packetSize = BitConverter.ToUInt16(tmp, 0)
  1038. session.bytesRecievedThisSecond += 2
  1039. ' Get the packet:
  1040. If theBuffer.Length <> packetSize Then ReDim theBuffer(packetSize - 1)
  1041. Do
  1042. ' Check to see if we're stopping...
  1043. If theServerIsStopping(Server, session) Then Exit Do
  1044. ' Read bytes in...
  1045. bytesread += Stream.Read(theBuffer, bytesread, (packetSize - bytesread))
  1046. Loop While bytesread < packetSize
  1047. bytesread = 0
  1048. ' Record bytes read for throttling...
  1049. session.bytesRecievedThisSecond += packetSize
  1050. ' Handle the packet...
  1051. If dataChannel > 250 Then
  1052. ' this is an internal system packet
  1053. If Not theServerIsStopping(Server, session) Then HandleIncomingSystemMessages(theBuffer, dataChannel, session)
  1054. Else
  1055. ' Hand user data off to the calling thread.
  1056. If Not theServerIsStopping(Server, session) Then RcvBytes(theBuffer, session, dataChannel)
  1057. End If
  1058. idleTimer = Now
  1059. End If
  1060. ' Throttle CPU usage when idle.
  1061. If Now > idleTimer.AddMilliseconds(500) Then
  1062. Thread.Sleep(50)
  1063. End If
  1064. Loop
  1065. Catch ex As Exception
  1066. ' An unexpected error.
  1067. Debug.WriteLine("Unexpected error in server: " & ex.Message)
  1068. End Try
  1069. Try
  1070. session.fileReader.Close()
  1071. Catch ex As Exception
  1072. End Try
  1073. Try
  1074. Server.Client.Close()
  1075. Server.Client.Blocking = False
  1076. Catch ex As Exception
  1077. End Try
  1078. ' If we're in the middle of receiving a file,
  1079. ' close the filestream, release the memory and
  1080. ' delete the partial file.
  1081. WrapUpIncomingFile(session)
  1082. session.IsRunning = False
  1083. SystemMessage("Session " & session.sessionID.ToString & " Stopped.")
  1084. End Sub
  1085. Protected Overrides Sub Finalize()
  1086. MyBase.Finalize()
  1087. End Sub
  1088. ' Receive message queue stuff
  1089. 'Private Class message
  1090. ' Public bytes() As Byte
  1091. ' Public dataChannel As Integer
  1092. ' Public sessionId As Int32
  1093. 'End Class
  1094. 'Private spinning As Boolean = False
  1095. 'Private addedMore As Boolean = False
  1096. 'Private receiveQueue As New ConcurrentQueue(Of message)
  1097. 'Private Sub AddToQueue(bytes() As Byte, dataChannel As Integer, ByRef session As SessionCommunications)
  1098. ' ' Throttle receiveQueue - 1st half
  1099. ' 'If receiveQueue.Count > 99 and Not session.pauseSent then
  1100. ' ' SendExternalSystemMessage("pause", session)
  1101. ' ' session.pauseSent = True
  1102. ' 'End If
  1103. ' Dim msg As New message
  1104. ' Dim theseBytes(bytes.Length - 1) As Byte
  1105. ' Array.Copy(bytes, theseBytes, bytes.Length)
  1106. ' msg.dataChannel = dataChannel
  1107. ' msg.sessionId = session.sessionID
  1108. ' msg.bytes = theseBytes
  1109. ' receiveQueue.Enqueue(msg)
  1110. ' If Not spinning then
  1111. ' Dim bgThread As New Thread(AddressOf DoSafeReceive)
  1112. ' bgThread.Start(session)
  1113. ' spinning = True
  1114. ' addedMore = False
  1115. ' Else
  1116. ' addedMore = True
  1117. ' End If
  1118. 'End Sub
  1119. 'Private Sub DoSafeReceive(ByVal _session As Object)
  1120. ' Dim msg As message = Nothing
  1121. ' Dim session As SessionCommunications = CType(_session, SessionCommunications)
  1122. ' While spinning
  1123. ' If receiveQueue.TryPeek(msg) then
  1124. ' receiveQueue.TryDequeue(msg)
  1125. ' ServerCallbackObject(msg.bytes, msg.sessionId, msg.dataChannel)
  1126. ' msg = Nothing
  1127. ' ' Throttle receive queue - 2nd half
  1128. ' 'If receiveQueue.Count <= 3 And session.pauseSent Then
  1129. ' ' SendExternalSystemMessage("resume", session)
  1130. ' ' session.pauseSent = False
  1131. ' 'End If
  1132. ' Else
  1133. ' Dim timer As Date = Now
  1134. ' While timer.AddMilliseconds(200) < Now
  1135. ' If receiveQueue.TryPeek(msg) then Exit While
  1136. ' End While
  1137. ' If Not receiveQueue.TryPeek(msg) then
  1138. ' spinning = False
  1139. ' Exit Sub
  1140. ' End If
  1141. ' End If
  1142. ' End While
  1143. 'End Sub
  1144. End Class