|
|
@ -19,57 +19,90 @@ import ( |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
// node-controlling states
|
|
|
|
// node-controlling states
|
|
|
|
type NodeInnerStates struct { |
|
|
|
type nodeInnerstates struct { |
|
|
|
Stopped bool // the way to exit the mainloop in case of an external error or a successful end of a transfer
|
|
|
|
Stopped bool // the way to exit the mainloop in case of an external error or a successful end of a transfer
|
|
|
|
AllowedToTransfer bool // the way to notify the mainloop of a sending node to start sending pieces of files
|
|
|
|
AllowedToTransfer bool // the way to notify the mainloop of a sending node to start sending pieces of files
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Network specific settings
|
|
|
|
// netInfowork specific settings
|
|
|
|
type Net struct { |
|
|
|
type netInfoInfo struct { |
|
|
|
ConnAddr string // address to connect to. Does not include port
|
|
|
|
ConnAddr string // address to connect to. Does not include port
|
|
|
|
Conn net.Conn // the core TCP connection of the node. Self-explanatory
|
|
|
|
Conn net.Conn // the core TCP connection of the node. Self-explanatory
|
|
|
|
Port uint // a port to connect to/listen on
|
|
|
|
Port uint // a port to connect to/listen on
|
|
|
|
EncryptionKey []byte // if != nil - incoming packets will be decrypted with it and outcoming packets will be encrypted
|
|
|
|
EncryptionKey []byte // if != nil - incoming packets will be decrypted with it and outcoming packets will be encrypted
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Both sending-side and receiving-side information
|
|
|
|
// Sending-side node information
|
|
|
|
type TransferInfo struct { |
|
|
|
type sending struct { |
|
|
|
Ready bool // is the other node ready to receive another piece
|
|
|
|
ServingPath string // path to the thing that will be sent
|
|
|
|
ServingPath string // path to the thing that will be sent
|
|
|
|
IsDirectory bool // is ServingPath a directory
|
|
|
|
Recursive bool // recursively send directory
|
|
|
|
Recursive bool // recursively send directory
|
|
|
|
|
|
|
|
CanSendBytes bool // is the other node ready to receive another piece
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Receiving-side node information
|
|
|
|
|
|
|
|
type receiving struct { |
|
|
|
AcceptedFiles []*fsys.File // files that`ve been accepted to be received
|
|
|
|
AcceptedFiles []*fsys.File // files that`ve been accepted to be received
|
|
|
|
DownloadsPath string // where to download
|
|
|
|
DownloadsPath string // where to download
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Both sending-side and receiving-side information
|
|
|
|
|
|
|
|
type transferInfo struct { |
|
|
|
|
|
|
|
Receiving *receiving |
|
|
|
|
|
|
|
Sending *sending |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Sender and receiver in one type !
|
|
|
|
// Sender and receiver in one type !
|
|
|
|
type Node struct { |
|
|
|
type Node struct { |
|
|
|
PacketPipe chan *protocol.Packet // a way to receive incoming packets from another goroutine
|
|
|
|
packetPipe chan *protocol.Packet // a way to receive incoming packets from another goroutine
|
|
|
|
IsSending bool // sending or a receiving node
|
|
|
|
isSending bool // sending or a receiving node
|
|
|
|
Net *Net |
|
|
|
netInfo *netInfoInfo |
|
|
|
State *NodeInnerStates |
|
|
|
state *nodeInnerstates |
|
|
|
TransferInfo *TransferInfo |
|
|
|
transferInfo *transferInfo |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Creates a new either a sending or receiving node with specified options
|
|
|
|
// Creates a new either a sending or receiving node with specified options
|
|
|
|
func NewNode(options *NodeOptions) (*Node, error) { |
|
|
|
func NewNode(options *NodeOptions) (*Node, error) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var isDir bool |
|
|
|
|
|
|
|
if options.IsSending { |
|
|
|
|
|
|
|
sendingPathStats, err := os.Stat(options.ServerSide.ServingPath) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
return nil, err |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch sendingPathStats.IsDir() { |
|
|
|
|
|
|
|
case true: |
|
|
|
|
|
|
|
isDir = true |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case false: |
|
|
|
|
|
|
|
isDir = false |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
node := Node{ |
|
|
|
node := Node{ |
|
|
|
PacketPipe: make(chan *protocol.Packet, 100), |
|
|
|
packetPipe: make(chan *protocol.Packet, 100), |
|
|
|
IsSending: options.IsSending, |
|
|
|
isSending: options.IsSending, |
|
|
|
Net: &Net{ |
|
|
|
netInfo: &netInfoInfo{ |
|
|
|
Port: options.WorkingPort, |
|
|
|
Port: options.WorkingPort, |
|
|
|
ConnAddr: options.ClientSide.ConnectionAddr, |
|
|
|
ConnAddr: options.ClientSide.ConnectionAddr, |
|
|
|
EncryptionKey: nil, |
|
|
|
EncryptionKey: nil, |
|
|
|
Conn: nil, |
|
|
|
Conn: nil, |
|
|
|
}, |
|
|
|
}, |
|
|
|
State: &NodeInnerStates{ |
|
|
|
state: &nodeInnerstates{ |
|
|
|
AllowedToTransfer: false, |
|
|
|
AllowedToTransfer: false, |
|
|
|
Stopped: false, |
|
|
|
Stopped: false, |
|
|
|
}, |
|
|
|
}, |
|
|
|
TransferInfo: &TransferInfo{ |
|
|
|
transferInfo: &transferInfo{ |
|
|
|
ServingPath: options.ServerSide.ServingPath, |
|
|
|
Sending: &sending{ |
|
|
|
Recursive: options.ServerSide.Recursive, |
|
|
|
ServingPath: options.ServerSide.ServingPath, |
|
|
|
AcceptedFiles: nil, |
|
|
|
Recursive: options.ServerSide.Recursive, |
|
|
|
DownloadsPath: options.ClientSide.DownloadsFolderPath, |
|
|
|
IsDirectory: isDir, |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
Receiving: &receiving{ |
|
|
|
|
|
|
|
AcceptedFiles: nil, |
|
|
|
|
|
|
|
DownloadsPath: options.ClientSide.DownloadsFolderPath, |
|
|
|
|
|
|
|
}, |
|
|
|
}, |
|
|
|
}, |
|
|
|
} |
|
|
|
} |
|
|
|
return &node, nil |
|
|
|
return &node, nil |
|
|
@ -77,41 +110,41 @@ func NewNode(options *NodeOptions) (*Node, error) { |
|
|
|
|
|
|
|
|
|
|
|
// Connect node to another listening one with a pre-defined address&&port
|
|
|
|
// Connect node to another listening one with a pre-defined address&&port
|
|
|
|
func (node *Node) connect() error { |
|
|
|
func (node *Node) connect() error { |
|
|
|
if node.Net.Port == 0 { |
|
|
|
if node.netInfo.Port == 0 { |
|
|
|
node.Net.Port = 7270 |
|
|
|
node.netInfo.Port = 7270 |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fmt.Printf("Connecting to %s:%d...\n", node.Net.ConnAddr, node.Net.Port) |
|
|
|
fmt.Printf("Connecting to %s:%d...\n", node.netInfo.ConnAddr, node.netInfo.Port) |
|
|
|
|
|
|
|
|
|
|
|
conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", node.Net.ConnAddr, node.Net.Port), time.Second*5) |
|
|
|
conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", node.netInfo.ConnAddr, node.netInfo.Port), time.Second*5) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
return err |
|
|
|
return err |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fmt.Printf("Connected\n") |
|
|
|
fmt.Printf("Connected\n") |
|
|
|
|
|
|
|
|
|
|
|
node.Net.Conn = conn |
|
|
|
node.netInfo.Conn = conn |
|
|
|
|
|
|
|
|
|
|
|
return nil |
|
|
|
return nil |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Notify the other node and close the connection
|
|
|
|
// Notify the other node and close the connection
|
|
|
|
func (node *Node) disconnect() error { |
|
|
|
func (node *Node) disconnect() error { |
|
|
|
if node.Net.Conn != nil { |
|
|
|
if node.netInfo.Conn != nil { |
|
|
|
// notify the other node and close the connection
|
|
|
|
// notify the other node and close the connection
|
|
|
|
err := protocol.SendPacket(node.Net.Conn, protocol.Packet{ |
|
|
|
err := protocol.SendPacket(node.netInfo.Conn, protocol.Packet{ |
|
|
|
Header: protocol.HeaderDisconnecting, |
|
|
|
Header: protocol.HeaderDisconnecting, |
|
|
|
}) |
|
|
|
}) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
return err |
|
|
|
return err |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
err = node.Net.Conn.Close() |
|
|
|
err = node.netInfo.Conn.Close() |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
return err |
|
|
|
return err |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
node.State.Stopped = true |
|
|
|
node.state.Stopped = true |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return nil |
|
|
|
return nil |
|
|
@ -119,7 +152,7 @@ func (node *Node) disconnect() error { |
|
|
|
|
|
|
|
|
|
|
|
// Wait for a connection on a pre-defined port
|
|
|
|
// Wait for a connection on a pre-defined port
|
|
|
|
func (node *Node) waitForConnection() error { |
|
|
|
func (node *Node) waitForConnection() error { |
|
|
|
listener, err := net.Listen("tcp", fmt.Sprintf(":%d", node.Net.Port)) |
|
|
|
listener, err := net.Listen("tcp", fmt.Sprintf(":%d", node.netInfo.Port)) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
return err |
|
|
|
return err |
|
|
|
} |
|
|
|
} |
|
|
@ -132,14 +165,14 @@ func (node *Node) waitForConnection() error { |
|
|
|
|
|
|
|
|
|
|
|
fmt.Printf("New connection from %s\n", connection.RemoteAddr().String()) |
|
|
|
fmt.Printf("New connection from %s\n", connection.RemoteAddr().String()) |
|
|
|
|
|
|
|
|
|
|
|
node.Net.Conn = connection |
|
|
|
node.netInfo.Conn = connection |
|
|
|
|
|
|
|
|
|
|
|
return nil |
|
|
|
return nil |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Starts the node in either sending or receiving state and performs the transfer
|
|
|
|
// Starts the node in either sending or receiving state and performs the transfer
|
|
|
|
func (node *Node) Start() { |
|
|
|
func (node *Node) Start() { |
|
|
|
switch node.IsSending { |
|
|
|
switch node.isSending { |
|
|
|
case true: |
|
|
|
case true: |
|
|
|
// SENDER
|
|
|
|
// SENDER
|
|
|
|
|
|
|
|
|
|
|
@ -149,11 +182,22 @@ func (node *Node) Start() { |
|
|
|
panic(err) |
|
|
|
panic(err) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
file, err := fsys.GetFile(node.TransferInfo.ServingPath) |
|
|
|
var file *fsys.File |
|
|
|
if err != nil { |
|
|
|
var dir *fsys.Directory |
|
|
|
panic(err) |
|
|
|
switch node.transferInfo.Sending.IsDirectory { |
|
|
|
|
|
|
|
case true: |
|
|
|
|
|
|
|
dir, err = fsys.GetDir(node.transferInfo.Sending.ServingPath, node.transferInfo.Sending.Recursive) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
panic(err) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
case false: |
|
|
|
|
|
|
|
file, err = fsys.GetFile(node.transferInfo.Sending.ServingPath) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
panic(err) |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
fmt.Printf("Sending \"%s\" (%.2f MB) locally on %s:%d\n", file.Name, float32(file.Size)/1024/1024, localIP, node.Net.Port) |
|
|
|
|
|
|
|
|
|
|
|
fmt.Printf("Sending \"%s\" (%.2f MB) locally on %s:%d\n", file.Name, float32(file.Size)/1024/1024, localIP, node.netInfo.Port) |
|
|
|
|
|
|
|
|
|
|
|
// wain for another node to connect
|
|
|
|
// wain for another node to connect
|
|
|
|
err = node.waitForConnection() |
|
|
|
err = node.waitForConnection() |
|
|
@ -163,35 +207,39 @@ func (node *Node) Start() { |
|
|
|
|
|
|
|
|
|
|
|
// generate and send encryption key
|
|
|
|
// generate and send encryption key
|
|
|
|
encrKey := encryption.Generate32AESkey() |
|
|
|
encrKey := encryption.Generate32AESkey() |
|
|
|
node.Net.EncryptionKey = encrKey |
|
|
|
node.netInfo.EncryptionKey = encrKey |
|
|
|
fmt.Printf("Generated encryption key: %s\n", encrKey) |
|
|
|
fmt.Printf("Generated encryption key: %s\n", encrKey) |
|
|
|
|
|
|
|
|
|
|
|
err = sendEncryptionKey(node.Net.Conn, encrKey) |
|
|
|
err = sendEncryptionKey(node.netInfo.Conn, encrKey) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
panic(err) |
|
|
|
panic(err) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// listen for incoming packets
|
|
|
|
// listen for incoming packets
|
|
|
|
go receivePackets(node.Net.Conn, node.PacketPipe) |
|
|
|
go receivePackets(node.netInfo.Conn, node.packetPipe) |
|
|
|
|
|
|
|
|
|
|
|
// send info on file/directory
|
|
|
|
// send info on file/directory
|
|
|
|
go sendFilePacket(node.Net.Conn, file, node.Net.EncryptionKey) |
|
|
|
if dir != nil { |
|
|
|
|
|
|
|
go sendDirectoryPacket(node.netInfo.Conn, dir, node.netInfo.EncryptionKey) |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
go sendFilePacket(node.netInfo.Conn, file, node.netInfo.EncryptionKey) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// mainloop
|
|
|
|
// mainloop
|
|
|
|
for { |
|
|
|
for { |
|
|
|
if node.State.Stopped { |
|
|
|
if node.state.Stopped { |
|
|
|
node.disconnect() |
|
|
|
node.disconnect() |
|
|
|
break |
|
|
|
break |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// receive incoming packets and decrypt them if necessary
|
|
|
|
// receive incoming packets and decrypt them if necessary
|
|
|
|
incomingPacket, ok := <-node.PacketPipe |
|
|
|
incomingPacket, ok := <-node.packetPipe |
|
|
|
if !ok { |
|
|
|
if !ok { |
|
|
|
node.State.Stopped = true |
|
|
|
node.state.Stopped = true |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if node.Net.EncryptionKey != nil { |
|
|
|
if node.netInfo.EncryptionKey != nil { |
|
|
|
err = incomingPacket.DecryptBody(node.Net.EncryptionKey) |
|
|
|
err = incomingPacket.DecryptBody(node.netInfo.EncryptionKey) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
panic(err) |
|
|
|
panic(err) |
|
|
|
} |
|
|
|
} |
|
|
@ -201,69 +249,83 @@ func (node *Node) Start() { |
|
|
|
switch incomingPacket.Header { |
|
|
|
switch incomingPacket.Header { |
|
|
|
case protocol.HeaderReady: |
|
|
|
case protocol.HeaderReady: |
|
|
|
// the other node is ready to receive file data
|
|
|
|
// the other node is ready to receive file data
|
|
|
|
node.TransferInfo.Ready = true |
|
|
|
node.transferInfo.Sending.CanSendBytes = true |
|
|
|
|
|
|
|
|
|
|
|
case protocol.HeaderAccept: |
|
|
|
case protocol.HeaderAccept: |
|
|
|
node.State.AllowedToTransfer = true |
|
|
|
node.state.AllowedToTransfer = true |
|
|
|
|
|
|
|
|
|
|
|
fmt.Printf("Transfer allowed. Sending...\n") |
|
|
|
fmt.Printf("Transfer allowed. Sending...\n") |
|
|
|
|
|
|
|
|
|
|
|
case protocol.HeaderReject: |
|
|
|
case protocol.HeaderReject: |
|
|
|
node.State.Stopped = true |
|
|
|
node.state.Stopped = true |
|
|
|
|
|
|
|
|
|
|
|
fmt.Printf("Transfer rejected. Disconnecting...") |
|
|
|
fmt.Printf("Transfer rejected. Disconnecting...") |
|
|
|
|
|
|
|
|
|
|
|
case protocol.HeaderDisconnecting: |
|
|
|
case protocol.HeaderDisconnecting: |
|
|
|
node.State.Stopped = true |
|
|
|
node.state.Stopped = true |
|
|
|
|
|
|
|
|
|
|
|
fmt.Printf("%s disconnected\n", node.Net.Conn.RemoteAddr()) |
|
|
|
fmt.Printf("%s disconnected\n", node.netInfo.Conn.RemoteAddr()) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// if allowed to transfer and the other node is ready to receive packets - send one piece
|
|
|
|
// if allowed to transfer and the other node is ready to receive packets - send one piece
|
|
|
|
// and wait for it to be ready again
|
|
|
|
// and wait for it to be ready again
|
|
|
|
if node.State.AllowedToTransfer && node.TransferInfo.Ready { |
|
|
|
if node.state.AllowedToTransfer && node.transferInfo.Sending.CanSendBytes { |
|
|
|
err = sendPiece(file, node.Net.Conn, node.Net.EncryptionKey) |
|
|
|
// handle a single file or a directory
|
|
|
|
switch err { |
|
|
|
switch node.transferInfo.Sending.IsDirectory { |
|
|
|
case ErrorSentAll: |
|
|
|
case true: |
|
|
|
// the file has been sent fully
|
|
|
|
// sending a file in a directory (possibly more than 1)
|
|
|
|
fileIDBuff := new(bytes.Buffer) |
|
|
|
if !node.transferInfo.Sending.Recursive { |
|
|
|
err = binary.Write(fileIDBuff, binary.BigEndian, file.ID) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
} else { |
|
|
|
panic(err) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
endFilePacket := protocol.Packet{ |
|
|
|
|
|
|
|
Header: protocol.HeaderEndfile, |
|
|
|
|
|
|
|
Body: fileIDBuff.Bytes(), |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if node.Net.EncryptionKey != nil { |
|
|
|
case false: |
|
|
|
err = endFilePacket.EncryptBody(node.Net.EncryptionKey) |
|
|
|
// sending a single file
|
|
|
|
|
|
|
|
err = sendPiece(file, node.netInfo.Conn, node.netInfo.EncryptionKey) |
|
|
|
|
|
|
|
switch err { |
|
|
|
|
|
|
|
case ErrorSentAll: |
|
|
|
|
|
|
|
// the file has been sent fully
|
|
|
|
|
|
|
|
fileIDBuff := new(bytes.Buffer) |
|
|
|
|
|
|
|
err = binary.Write(fileIDBuff, binary.BigEndian, file.ID) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
panic(err) |
|
|
|
panic(err) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protocol.SendPacket(node.Net.Conn, endFilePacket) |
|
|
|
endFilePacket := protocol.Packet{ |
|
|
|
|
|
|
|
Header: protocol.HeaderEndfile, |
|
|
|
|
|
|
|
Body: fileIDBuff.Bytes(), |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// because there`s still no handling for directories - send
|
|
|
|
if node.netInfo.EncryptionKey != nil { |
|
|
|
// done packet
|
|
|
|
err = endFilePacket.EncryptBody(node.netInfo.EncryptionKey) |
|
|
|
protocol.SendPacket(node.Net.Conn, protocol.Packet{ |
|
|
|
if err != nil { |
|
|
|
Header: protocol.HeaderDone, |
|
|
|
panic(err) |
|
|
|
}) |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
node.State.Stopped = true |
|
|
|
protocol.SendPacket(node.netInfo.Conn, endFilePacket) |
|
|
|
|
|
|
|
|
|
|
|
case nil: |
|
|
|
// because there`s still no handling for directories - send
|
|
|
|
|
|
|
|
// done packet
|
|
|
|
|
|
|
|
protocol.SendPacket(node.netInfo.Conn, protocol.Packet{ |
|
|
|
|
|
|
|
Header: protocol.HeaderDone, |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
default: |
|
|
|
node.state.Stopped = true |
|
|
|
node.State.Stopped = true |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fmt.Printf("An error occured while sending a piece of \"%s\": %s\n", file.Name, err) |
|
|
|
case nil: |
|
|
|
panic(err) |
|
|
|
|
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
node.state.Stopped = true |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fmt.Printf("An error occured while sending a piece of \"%s\": %s\n", file.Name, err) |
|
|
|
|
|
|
|
panic(err) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
node.transferInfo.Sending.CanSendBytes = false |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
node.TransferInfo.Ready = false |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -273,27 +335,27 @@ func (node *Node) Start() { |
|
|
|
// connect to the sending node
|
|
|
|
// connect to the sending node
|
|
|
|
err := node.connect() |
|
|
|
err := node.connect() |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
fmt.Printf("Could not connect to %s:%d\n", node.Net.ConnAddr, node.Net.Port) |
|
|
|
fmt.Printf("Could not connect to %s:%d\n", node.netInfo.ConnAddr, node.netInfo.Port) |
|
|
|
os.Exit(-1) |
|
|
|
os.Exit(-1) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// listen for incoming packets
|
|
|
|
// listen for incoming packets
|
|
|
|
go receivePackets(node.Net.Conn, node.PacketPipe) |
|
|
|
go receivePackets(node.netInfo.Conn, node.packetPipe) |
|
|
|
|
|
|
|
|
|
|
|
// mainloop
|
|
|
|
// mainloop
|
|
|
|
for { |
|
|
|
for { |
|
|
|
if node.State.Stopped { |
|
|
|
if node.state.Stopped { |
|
|
|
node.disconnect() |
|
|
|
node.disconnect() |
|
|
|
break |
|
|
|
break |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// receive incoming packets and decrypt them if necessary
|
|
|
|
// receive incoming packets and decrypt them if necessary
|
|
|
|
incomingPacket, ok := <-node.PacketPipe |
|
|
|
incomingPacket, ok := <-node.packetPipe |
|
|
|
if !ok { |
|
|
|
if !ok { |
|
|
|
break |
|
|
|
break |
|
|
|
} |
|
|
|
} |
|
|
|
if node.Net.EncryptionKey != nil { |
|
|
|
if node.netInfo.EncryptionKey != nil { |
|
|
|
err = incomingPacket.DecryptBody(node.Net.EncryptionKey) |
|
|
|
err = incomingPacket.DecryptBody(node.netInfo.EncryptionKey) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
panic(err) |
|
|
|
panic(err) |
|
|
|
} |
|
|
|
} |
|
|
@ -322,12 +384,12 @@ func (node *Node) Start() { |
|
|
|
if strings.EqualFold(answer, "y") || answer == "" { |
|
|
|
if strings.EqualFold(answer, "y") || answer == "" { |
|
|
|
// yes
|
|
|
|
// yes
|
|
|
|
|
|
|
|
|
|
|
|
err = os.MkdirAll(node.TransferInfo.DownloadsPath, os.ModePerm) |
|
|
|
err = os.MkdirAll(node.transferInfo.Receiving.DownloadsPath, os.ModePerm) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
panic(err) |
|
|
|
panic(err) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fullFilePath := filepath.Join(node.TransferInfo.DownloadsPath, file.Name) |
|
|
|
fullFilePath := filepath.Join(node.transferInfo.Receiving.DownloadsPath, file.Name) |
|
|
|
|
|
|
|
|
|
|
|
// check if the file already exists; if yes - remove it and replace with a new one
|
|
|
|
// check if the file already exists; if yes - remove it and replace with a new one
|
|
|
|
_, err := os.Stat(fullFilePath) |
|
|
|
_, err := os.Stat(fullFilePath) |
|
|
@ -340,28 +402,28 @@ func (node *Node) Start() { |
|
|
|
file.Path = fullFilePath |
|
|
|
file.Path = fullFilePath |
|
|
|
file.Open() |
|
|
|
file.Open() |
|
|
|
|
|
|
|
|
|
|
|
node.TransferInfo.AcceptedFiles = append(node.TransferInfo.AcceptedFiles, file) |
|
|
|
node.transferInfo.Receiving.AcceptedFiles = append(node.transferInfo.Receiving.AcceptedFiles, file) |
|
|
|
|
|
|
|
|
|
|
|
// send aceptance packet
|
|
|
|
// send aceptance packet
|
|
|
|
acceptancePacket := protocol.Packet{ |
|
|
|
acceptancePacket := protocol.Packet{ |
|
|
|
Header: protocol.HeaderAccept, |
|
|
|
Header: protocol.HeaderAccept, |
|
|
|
Body: responsePacketFileIDBuffer.Bytes(), |
|
|
|
Body: responsePacketFileIDBuffer.Bytes(), |
|
|
|
} |
|
|
|
} |
|
|
|
if node.Net.EncryptionKey != nil { |
|
|
|
if node.netInfo.EncryptionKey != nil { |
|
|
|
err = acceptancePacket.EncryptBody(node.Net.EncryptionKey) |
|
|
|
err = acceptancePacket.EncryptBody(node.netInfo.EncryptionKey) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
panic(err) |
|
|
|
panic(err) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
err = protocol.SendPacket(node.Net.Conn, acceptancePacket) |
|
|
|
err = protocol.SendPacket(node.netInfo.Conn, acceptancePacket) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
panic(err) |
|
|
|
panic(err) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// notify the node that we`re ready to transportation. No need
|
|
|
|
// notify the node that we`re ready to transportation. No need
|
|
|
|
// for encryption because the body is nil
|
|
|
|
// for encryption because the body is nil
|
|
|
|
err = protocol.SendPacket(node.Net.Conn, protocol.Packet{ |
|
|
|
err = protocol.SendPacket(node.netInfo.Conn, protocol.Packet{ |
|
|
|
Header: protocol.HeaderReady, |
|
|
|
Header: protocol.HeaderReady, |
|
|
|
}) |
|
|
|
}) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
@ -375,19 +437,19 @@ func (node *Node) Start() { |
|
|
|
Body: responsePacketFileIDBuffer.Bytes(), |
|
|
|
Body: responsePacketFileIDBuffer.Bytes(), |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if node.Net.EncryptionKey != nil { |
|
|
|
if node.netInfo.EncryptionKey != nil { |
|
|
|
err = rejectionPacket.EncryptBody(node.Net.EncryptionKey) |
|
|
|
err = rejectionPacket.EncryptBody(node.netInfo.EncryptionKey) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
panic(err) |
|
|
|
panic(err) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
err = protocol.SendPacket(node.Net.Conn, rejectionPacket) |
|
|
|
err = protocol.SendPacket(node.netInfo.Conn, rejectionPacket) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
panic(err) |
|
|
|
panic(err) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
node.State.Stopped = true |
|
|
|
node.state.Stopped = true |
|
|
|
} |
|
|
|
} |
|
|
|
}() |
|
|
|
}() |
|
|
|
|
|
|
|
|
|
|
@ -400,7 +462,7 @@ func (node *Node) Start() { |
|
|
|
panic(err) |
|
|
|
panic(err) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
for _, acceptedFile := range node.TransferInfo.AcceptedFiles { |
|
|
|
for _, acceptedFile := range node.transferInfo.Receiving.AcceptedFiles { |
|
|
|
if acceptedFile.ID == fileID { |
|
|
|
if acceptedFile.ID == fileID { |
|
|
|
// accepted
|
|
|
|
// accepted
|
|
|
|
|
|
|
|
|
|
|
@ -415,7 +477,7 @@ func (node *Node) Start() { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// notify the other one that this node is ready
|
|
|
|
// notify the other one that this node is ready
|
|
|
|
err = protocol.SendPacket(node.Net.Conn, protocol.Packet{ |
|
|
|
err = protocol.SendPacket(node.netInfo.Conn, protocol.Packet{ |
|
|
|
Header: protocol.HeaderReady, |
|
|
|
Header: protocol.HeaderReady, |
|
|
|
}) |
|
|
|
}) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
@ -434,7 +496,7 @@ func (node *Node) Start() { |
|
|
|
panic(err) |
|
|
|
panic(err) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
for index, acceptedFile := range node.TransferInfo.AcceptedFiles { |
|
|
|
for index, acceptedFile := range node.transferInfo.Receiving.AcceptedFiles { |
|
|
|
if acceptedFile.ID == fileID { |
|
|
|
if acceptedFile.ID == fileID { |
|
|
|
// accepted
|
|
|
|
// accepted
|
|
|
|
|
|
|
|
|
|
|
@ -442,7 +504,7 @@ func (node *Node) Start() { |
|
|
|
defer acceptedFile.Handler.Close() |
|
|
|
defer acceptedFile.Handler.Close() |
|
|
|
|
|
|
|
|
|
|
|
// remove this file from the pool
|
|
|
|
// remove this file from the pool
|
|
|
|
node.TransferInfo.AcceptedFiles = append(node.TransferInfo.AcceptedFiles[:index], node.TransferInfo.AcceptedFiles[index+1:]...) |
|
|
|
node.transferInfo.Receiving.AcceptedFiles = append(node.transferInfo.Receiving.AcceptedFiles[:index], node.transferInfo.Receiving.AcceptedFiles[index+1:]...) |
|
|
|
|
|
|
|
|
|
|
|
// compare checksums
|
|
|
|
// compare checksums
|
|
|
|
realChecksum, err := checksum.GetPartialCheckSum(acceptedFile.Handler) |
|
|
|
realChecksum, err := checksum.GetPartialCheckSum(acceptedFile.Handler) |
|
|
@ -461,7 +523,7 @@ func (node *Node) Start() { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// node.State.Stopped = true
|
|
|
|
// node.state.Stopped = true
|
|
|
|
|
|
|
|
|
|
|
|
case protocol.HeaderEncryptionKey: |
|
|
|
case protocol.HeaderEncryptionKey: |
|
|
|
// retrieve the key
|
|
|
|
// retrieve the key
|
|
|
@ -473,15 +535,15 @@ func (node *Node) Start() { |
|
|
|
encrKey := make([]byte, keySize) |
|
|
|
encrKey := make([]byte, keySize) |
|
|
|
packetReader.Read(encrKey) |
|
|
|
packetReader.Read(encrKey) |
|
|
|
|
|
|
|
|
|
|
|
node.Net.EncryptionKey = encrKey |
|
|
|
node.netInfo.EncryptionKey = encrKey |
|
|
|
|
|
|
|
|
|
|
|
case protocol.HeaderDone: |
|
|
|
case protocol.HeaderDone: |
|
|
|
node.State.Stopped = true |
|
|
|
node.state.Stopped = true |
|
|
|
|
|
|
|
|
|
|
|
case protocol.HeaderDisconnecting: |
|
|
|
case protocol.HeaderDisconnecting: |
|
|
|
node.State.Stopped = true |
|
|
|
node.state.Stopped = true |
|
|
|
|
|
|
|
|
|
|
|
fmt.Printf("%s disconnected\n", node.Net.Conn.RemoteAddr()) |
|
|
|
fmt.Printf("%s disconnected\n", node.netInfo.Conn.RemoteAddr()) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|