First completly working solution
This commit is contained in:
148
packets.go
Normal file
148
packets.go
Normal file
@@ -0,0 +1,148 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
const HeaderSize int = 32 + 1 + 4 + 4
|
||||
|
||||
type SessionID [32]byte
|
||||
|
||||
type Packet struct {
|
||||
// headerLength uint32
|
||||
sid SessionID
|
||||
flag HeaderFlag
|
||||
sync uint32
|
||||
dataLength uint32
|
||||
data []byte
|
||||
}
|
||||
|
||||
func PacketFromBytes(bytes []byte) Packet {
|
||||
sid := SessionID(bytes[0:32])
|
||||
flag := HeaderFlag(bytes[32])
|
||||
sync := binary.LittleEndian.Uint32(bytes[33:37])
|
||||
dataLength := binary.LittleEndian.Uint32(bytes[37:41])
|
||||
pck := Packet{
|
||||
sid: sid,
|
||||
flag: flag,
|
||||
sync: sync,
|
||||
dataLength: dataLength,
|
||||
data: bytes[41 : 41+dataLength],
|
||||
}
|
||||
return pck
|
||||
}
|
||||
|
||||
func NewAck(pckToAck *Packet) *Packet {
|
||||
data := make([]byte, 4)
|
||||
binary.LittleEndian.PutUint32(data, pckToAck.sync)
|
||||
return &Packet{
|
||||
sid: pckToAck.sid,
|
||||
flag: Ack,
|
||||
sync: pckToAck.sync + 1,
|
||||
dataLength: uint32(4),
|
||||
data: data,
|
||||
}
|
||||
}
|
||||
|
||||
func NewRequest(path string) *Packet {
|
||||
data := []byte(path)
|
||||
buf := make([]byte, 32)
|
||||
_, err := rand.Read(buf)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return &Packet{
|
||||
sid: SessionID(buf),
|
||||
flag: Request,
|
||||
sync: 0,
|
||||
dataLength: uint32(len(data)),
|
||||
data: data,
|
||||
}
|
||||
}
|
||||
|
||||
func NewFile(lastPck *Packet, data []byte) *Packet {
|
||||
return &Packet{
|
||||
sid: lastPck.sid,
|
||||
flag: File,
|
||||
sync: lastPck.sync + 1,
|
||||
dataLength: uint32(len(data)),
|
||||
data: data,
|
||||
}
|
||||
}
|
||||
|
||||
func NewEnd(lastFilePck *Packet) *Packet {
|
||||
data := make([]byte, 4)
|
||||
binary.LittleEndian.PutUint32(data, lastFilePck.sync)
|
||||
return &Packet{
|
||||
sid: lastFilePck.sid,
|
||||
flag: End,
|
||||
sync: lastFilePck.sync + 1,
|
||||
dataLength: uint32(4),
|
||||
data: data,
|
||||
}
|
||||
}
|
||||
|
||||
func NewResend(sync uint32, lastPck *Packet) *Packet {
|
||||
data := make([]byte, 4)
|
||||
binary.LittleEndian.PutUint32(data, sync)
|
||||
return &Packet{
|
||||
sid: lastPck.sid,
|
||||
flag: Resend,
|
||||
sync: lastPck.sync + 1,
|
||||
dataLength: uint32(4),
|
||||
data: data,
|
||||
}
|
||||
}
|
||||
|
||||
func NewPte(fileSize uint32, lastPck *Packet) *Packet {
|
||||
data := make([]byte, 4)
|
||||
binary.LittleEndian.PutUint32(data, fileSize)
|
||||
return &Packet{
|
||||
sid: lastPck.sid,
|
||||
flag: PTE,
|
||||
sync: lastPck.sync + 1,
|
||||
dataLength: uint32(4),
|
||||
data: data,
|
||||
}
|
||||
}
|
||||
|
||||
func (pck *Packet) GetUint32Payload() (uint32, error) {
|
||||
flag := pck.flag
|
||||
if flag != PTE && flag != Ack && flag != End && flag != Resend {
|
||||
return 0, errors.New(fmt.Sprintf("Can not get Sync from Packet Type with flag: %v", flag))
|
||||
}
|
||||
return binary.LittleEndian.Uint32(pck.data), nil
|
||||
}
|
||||
|
||||
func (pck *Packet) GetFilePath() (string, error) {
|
||||
if pck.flag != Request {
|
||||
return "", errors.New("Can not get FilePath from Packet that is not Request")
|
||||
}
|
||||
return string(pck.data), nil
|
||||
}
|
||||
|
||||
func (pck *Packet) ToBytes() []byte {
|
||||
arr := make([]byte, HeaderSize+int(pck.dataLength))
|
||||
copy(arr[0:32], pck.sid[:])
|
||||
arr[32] = byte(pck.flag)
|
||||
binary.LittleEndian.PutUint32(arr[33:37], pck.sync)
|
||||
binary.LittleEndian.PutUint32(arr[37:41], pck.dataLength)
|
||||
copy(arr[41:], pck.data)
|
||||
|
||||
return arr
|
||||
}
|
||||
|
||||
type HeaderFlag uint8
|
||||
|
||||
const (
|
||||
Request HeaderFlag = iota
|
||||
PTE HeaderFlag = iota
|
||||
Ack HeaderFlag = iota
|
||||
File HeaderFlag = iota
|
||||
End HeaderFlag = iota
|
||||
Resend HeaderFlag = iota
|
||||
)
|
||||
Reference in New Issue
Block a user