Imports System
Imports Microsoft
Imports Microsoft.VisualBasic
Imports System.AppDomain
Module Module1
Public mCl As New client
Public running As Boolean = True
Public mainform As Form1
Public udp As UDPMaster '(2002) 'local port
Sub SendOut()
If mCl.clientID = -1 Then
Static LoginPause As Long
If Not Environment.TickCount - LoginPause < 1000 Then
Dim bar(2) As Byte
udp.Send(mCl.IP, mCl.port, bar)
'BetCon("Sent LOGIN REQ")
mCl.ChCon(1)
mCl.inSeq = 1
mCl.outSeq = 0
mCl.sendBuffer = New Collection
mCl.inBuffer = New Collection
LoginPause = Environment.TickCount
'clientID = 0
End If
Exit Sub
End If
'go through all packets
If mCl.sendBuffer.Count > 0 Then
Dim j = 0
Dim dg As UDPMaster.DGram
Dim RemQ As New Queue
For j = 1 To mCl.sendBuffer.Count
dg = mCl.sendBuffer(j)
If Environment.TickCount - dg.lastSendOut < mCl.pressure Then GoTo nextJ
dg.lastSendOut = Environment.TickCount
Dim dt As String = UDPMaster.BytesToString(dg.data, UBound(dg.data)).Substring(2)
Dim snm = UnBinNum(dt)
'This is a good place to discard old/outdated packets
'BetCon("[" & snm & "] Sending..:" & dt)
If udp.Send(dg) = False Then mCl.ChCon(3)
mCl.lastSendOut = Environment.TickCount
nextJ:
Next
Do While RemQ.Count > 0
Dim ij = RemQ.Dequeue
mCl.sendBuffer.Remove(ij)
Loop
End If
End Sub
Function LearnSEQ(ByRef data As Byte()) As Integer
Dim dt As String = UDPMaster.BytesToString(data, UBound(data)).Substring(2)
Dim snm As Integer = UnBinNum(dt)
Return snm
End Function
Public Sub betset(ByRef x As Form1)
mainform = x
End Sub
Public Sub betCon(ByVal str As String)
mainform.TextBox1.AppendText(str & vbCrLf)
End Sub
Sub CollectData()
Dim Dgram As UDPMaster.DGram
Dim data As Byte()
Dim skip = udp.datagrams.Count + 1
Dim sskip = 0
'udp.RadioThread.Suspend()
Do While udp.Poll(Dgram)
sskip += 1
If Dgram.Port = 0 Then GoTo nextPacket
' first we must find out intent of packet
data = Dgram.data
'BetCon("DATA ARRIVED" & data(0) & "-" & data(1))
If data Is Nothing Then mCl.ChCon(3) : GoTo nextPacket
' If sskip = skip Then Exit Do
Dim strData As String = udp.BytesToString(data, UBound(data)).Substring(2)
Dim seqNum As Integer ' We don't know yet is it IN or OUT seq
seqNum = UnBinNum(strData)
If (data(0) <> 0 And mCl.clientID < 1) Or mCl.connState = 3 Then ' A bit ugly
mCl.ChCon(2)
End If
If mCl.clientID <> data(0) Then
betCon("NEW CLIENT ID:" & data(0))
End If
mCl.clientID = data(0)
If data(0) + data(1) + seqNum = 0 Then mCl.clientID = -1 : mCl.ChCon(3) : Exit Sub
'>>>>>>>>>>>>>>>>>>>>
'MAIN SHIT
'<<<<<<<<<<<<<<<<<<<<
Select Case data(1)
Case Is = 0 'ACK
'server acks packet he received
'THIS IS GOOD NEWS - we may move to next!
' mcl.outSeq += 1
'If seqNum = outSeq Then
'outSeq += 1
'BetCon("server reports on completion of " & seqNum & " packet! hoorah")
mCl.Done(seqNum)
'End If
Case Is = 1
mCl.Done(seqNum, True)
Case Is = 2 'INF
'BetCon("PEEK:" & strData.Length & "." & strData)
'Server sends YOU a packet and waits for your ACK
If seqNum = mCl.inSeq Then ' ONE WE WAITED FOR
udp.Send(mCl.IP, mCl.port, mCl.ComposeACK)
'BetCon("sent ack for " & inSeq)
mCl.inSeq += 1
'Actual CUSTOM protocol is HERE
'you might do something fancy like calling a different SUB
'or even using CallByName
'Here are the commands client can receive from server
If strData.StartsWith("SAY ") Then 'Simplest form of message
betCon(strData.Substring(4))
End If
If strData.StartsWith("FILEC") Then 'CLose file
mCl.fs.Close()
betCon("FILE COMPLETED!")
End If
If strData.StartsWith("FILEO ") Then 'Open file
Dim ministr = strData.Substring(6)
mCl.fn = ministr
mCl.fileLength = UnBinNum(ministr)
mCl.fileSize = 0
mCl.fs = New IO.FileStream(ministr, IO.FileMode.Create)
mCl.Compose("CHUNK")
mCl.fileStarTime = Environment.TickCount
End If
If strData.StartsWith("BYTE") Then 'Piece of file
'Dim pos As Int32 = UnBinNum(strData)
Dim doto() As Byte = UDPMaster.StringToBytes(strData.Substring(5))
End If
If strData = "BEND" Then ' Next segment of file availible
mCl.Compose("CHUNK")
End If
If strData = "HELLO" Then ' First thing client receives after a handshake. MUST respond with 'HI'
betCon("Received H E L L O ")
mCl.Compose("HI")
End If
If strData = "GO" Then ' Usefull In turn-based applications, not used here
Dim draken$ '= Console.ReadLine()
If draken$ = "QUIT" Then running = False
mCl.Compose(draken$)
End If
'BetCon("acked")
GoTo nextPacket
End If
If seqNum < mCl.inSeq Then ' OLD ONE' ASK SERVER TO STOP THIS FLOOD
udp.Send(mCl.IP, mCl.port, mCl.ComposeBUF(seqNum))
'BetCon("recvd old packet:" & strData)
End If
If seqNum > mCl.inSeq Then ' ONE FROM THE FUTURE
' LET'S BUFFER IT FOR FUTURE USE
Dim i = HasInBuffer(seqNum)
If i = -1 Then
mCl.inBuffer.Add(Dgram)
End If
udp.Send(mCl.IP, mCl.port, mCl.ComposeBUF(seqNum))
End If
End Select
nextPacket:
Loop
'SPOOF BUFFER
Dim k = HasInBuffer(mCl.inSeq)
If k <> -1 Then
udp.datagrams.Enqueue(mCl.inBuffer(k)) ' SPOOF IT
mCl.inBuffer.Remove(k) ' ADD DELETE FROM LIST
End If
'udp.RadioThread.Resume()
End Sub
Function HasInBuffer(ByVal ASeqNum As Integer) As Integer
Dim j = -1
Dim k
For k = 1 To mCl.inBuffer.Count
Dim duq As UDPMaster.DGram
duq = mCl.inBuffer.Item(k)
Dim strData As String = udp.BytesToString(duq.data, UBound(duq.data)).Substring(2)
Dim seqNum As Integer ' We don't know yet is it IN or OUT seq
seqNum = UnBinNum(strData)
If seqNum = ASeqNum Then j = k : Exit For
Next k
Return j
End Function