diff --git a/cmd/main.go b/cmd/main.go index f1942eb..770cff3 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -55,6 +55,14 @@ func main() { eraseErrorRule := writers.CreateEraseErrorRule("^ERASE_ERROR\r\n$") protocolRepository.AddWriter(&eraseErrorRule) + // Creation of the EraseOkRule + retrieveOkRule := writers.CreateRetrieveOkRule("^RETRIEVE_OK ([A-Za-z0-9.]{50,200} [0-9]{1,10} [A-Za-z0-9.]{50,200})\r\n$", appConfig.StoragePath) + protocolRepository.AddWriter(&retrieveOkRule) + + // Creation of the EraseErrorRule + retrieveErrorRule := writers.CreateRetrieveErrorRule("^RETRIEVE_ERROR\r\n$") + protocolRepository.AddWriter(&retrieveErrorRule) + /** ===== Init all Reader here ===== */ @@ -62,10 +70,14 @@ func main() { eraseFileRule := readers.CreateEraseFileRule("^ERASEFILE ([A-Za-z0-9.]{50,200})\r\n$", protocolRepository, appConfig.StoragePath) protocolRepository.AddReader(&eraseFileRule) - // Creation of the SendFileRule // TODO reset to 50,200 - sendFileRule := readers.CreateSendFileRule("^SENDFILE ([A-Za-z0-9.]{1,200}) ([0-9]{1,10}) ([A-Za-z0-9.]{50,200})\r\n$", protocolRepository, appConfig.StoragePath) + // Creation of the SendFileRule + sendFileRule := readers.CreateSendFileRule("^SENDFILE ([A-Za-z0-9.]{50,200}) ([0-9]{1,10}) ([A-Za-z0-9.]{50,200})\r\n$", protocolRepository, appConfig.StoragePath) protocolRepository.AddReader(&sendFileRule) + // Create of the RetrieveFileRule + retrieveFileRule := readers.CreateRetrieveFileRule("^RETRIEVEFILE ([A-Za-z0-9.]{50,200})\r\n$", protocolRepository, appConfig.StoragePath) + protocolRepository.AddReader(&retrieveFileRule) + // Create a Multicast Client & run it multicast := network.CreateClientMulticast( appConfig.MulticastNetworkInterface, appConfig.MulticastAddress, appConfig.Domain, diff --git a/pkg/network/ClientMulticast.go b/pkg/network/ClientMulticast.go index 49f97c6..5e96aa3 100644 --- a/pkg/network/ClientMulticast.go +++ b/pkg/network/ClientMulticast.go @@ -3,6 +3,7 @@ package network import ( "StoreBackEnd/pkg/protocol/repository" "StoreBackEnd/pkg/protocol/rules/writers" + "StoreBackEnd/pkg/utils" "fmt" "net" "time" @@ -48,6 +49,7 @@ func (client ClientMulticast) Run() { // Resolve interface addr lAddr, failedRIA := ResolveInterfaceAddr(client.netInter) if failedRIA { + println("Error : No IPv4 found in interface") return } @@ -81,21 +83,18 @@ func (client ClientMulticast) ResolveAddr() (*net.UDPAddr, bool) { // ResolveInterfaceAddr Resolves the network interface address. func ResolveInterfaceAddr(inter string) (*net.UDPAddr, bool) { - //ief, _ := net.InterfaceByName(inter) - //addrs, _ := ief.Addrs() - //for _, addr := range addrs { - // if utils.IsIPv4(addr.String()) { - // println("Selected IP", addr.String()) - // lAddr, _ := net.ResolveUDPAddr("udp", "127.0.0.1:15502") - // return lAddr, false - // } - //} - return nil, false + ip, err := utils.RetrieveIPv4FromInterface(inter) + if err != nil { + println("Error while loading interface : " + err.Error()) + return nil, true + } + println("Selected IP for multicast : " + ip.String()) + return &net.UDPAddr{IP: ip}, false } // DialUdp Ouvre une connection UDP func (client ClientMulticast) DialUdp(lAddr *net.UDPAddr, rAddr *net.UDPAddr) (*net.UDPConn, bool) { - con, errDial := net.DialUDP("udp", nil, rAddr) + con, errDial := net.DialUDP("udp", lAddr, rAddr) if errDial != nil { println(errDial.Error()) return nil, true diff --git a/pkg/protocol/rules/readers/RetrieveFileRule.go b/pkg/protocol/rules/readers/RetrieveFileRule.go new file mode 100644 index 0000000..6b080f9 --- /dev/null +++ b/pkg/protocol/rules/readers/RetrieveFileRule.go @@ -0,0 +1,60 @@ +package readers + +import ( + "StoreBackEnd/pkg/protocol" + "StoreBackEnd/pkg/protocol/repository" + "StoreBackEnd/pkg/protocol/rules/writers" + "StoreBackEnd/pkg/utils" + "bufio" + "fmt" + "os" +) + +// RetrieveFileRulePrefix Identifiant de cette règle +const RetrieveFileRulePrefix = "RETRIEVEFILE" + +// RetrieveFileRule Demande de suppression d'un fichier +type RetrieveFileRule struct { + // Cmd Nom de la règle + Cmd string + // matcher Permet de vérifier le matching + matcher *protocol.RegexMatcher + // protocolRepo Instance de ProtocolRepository + protocolRepo *repository.ProtocolRepository + // storagePath Chemin de stockage du fichier + storagePath string +} + +// CreateRetrieveFileRule Création d'une instance de RetrieveFileRule +func CreateRetrieveFileRule(pattern string, protocolRepo *repository.ProtocolRepository, storagePath string) protocol.IProtocolReader { + return &RetrieveFileRule{ + Cmd: RetrieveFileRulePrefix, + matcher: protocol.CreateRegexMatcher(pattern), + protocolRepo: protocolRepo, + storagePath: storagePath, + } +} + +func (rule RetrieveFileRule) GetCmd() string { + return rule.Cmd +} + +func (rule RetrieveFileRule) Execute(data string) (*protocol.ProtocolWriterResult, func(reader *bufio.Reader) *protocol.ProtocolWriterResult) { + + if rule.Match(data) { + values := rule.matcher.Parse(data) + hashFileName := values[1] + + path := fmt.Sprintf("%s/%s", rule.storagePath, hashFileName) + if fileinfo, err := os.Stat(path); err == nil { + println("OKOKOKOEKOEKE : ", hashFileName, fmt.Sprintf("%d", fileinfo.Size()), fmt.Sprintf("%x", utils.GenFingerPrint(path))) + + return rule.protocolRepo.ExecuteWriter(writers.RetrieveOkRulePrefix, hashFileName, fmt.Sprintf("%d", fileinfo.Size()), fmt.Sprintf("%x", utils.GenFingerPrint(path))), nil + } + } + return rule.protocolRepo.ExecuteWriter(writers.RetrieveErrorRulePrefix), nil +} + +func (rule RetrieveFileRule) Match(data string) bool { + return rule.matcher.Match(data) +} diff --git a/pkg/protocol/rules/readers/SendFileRule.go b/pkg/protocol/rules/readers/SendFileRule.go index cd0d849..7e8f21d 100644 --- a/pkg/protocol/rules/readers/SendFileRule.go +++ b/pkg/protocol/rules/readers/SendFileRule.go @@ -12,7 +12,7 @@ import ( ) // SendFileRulePrefix Rule command prefix -const SendFileRulePrefix = "ffe_sendfile" +const SendFileRulePrefix = "SENDFILE" // SendFileRule Storage structure for the SendFileRule type SendFileRule struct { diff --git a/pkg/protocol/rules/writers/RetrieveErrorRule.go b/pkg/protocol/rules/writers/RetrieveErrorRule.go new file mode 100644 index 0000000..27edeb0 --- /dev/null +++ b/pkg/protocol/rules/writers/RetrieveErrorRule.go @@ -0,0 +1,38 @@ +package writers + +import ( + "StoreBackEnd/pkg/protocol" +) + +// RetrieveErrorRulePrefix Rule command prefix +const RetrieveErrorRulePrefix = "RETRIEVE_ERROR" + +// RetrieveErrorRule Storage structure for the RetrieveErrorRule +type RetrieveErrorRule struct { + // cmd Rule name + cmd string + // matcher Allow to make a regex match + matcher *protocol.RegexMatcher +} + +// CreateRetrieveErrorRule Creating an instance of RetrieveErrorRule +func CreateRetrieveErrorRule(pattern string) protocol.IProtocolWriter { + return &RetrieveErrorRule{ + cmd: RetrieveErrorRulePrefix, + matcher: protocol.CreateRegexMatcher(pattern), + } +} + +// GetCmd retrieve the command name. +func (rule RetrieveErrorRule) GetCmd() string { + return rule.cmd +} + +// Execute the Rule with a string command. +func (rule RetrieveErrorRule) Execute(argsData ...string) *protocol.ProtocolWriterResult { + buildedCmd, _ := rule.matcher.Build(RetrieveErrorRulePrefix, argsData...) + + return &protocol.ProtocolWriterResult{ + Cmd: buildedCmd, + } +} diff --git a/pkg/protocol/rules/writers/RetrieveOkRule.go b/pkg/protocol/rules/writers/RetrieveOkRule.go new file mode 100644 index 0000000..0270fe7 --- /dev/null +++ b/pkg/protocol/rules/writers/RetrieveOkRule.go @@ -0,0 +1,58 @@ +package writers + +import ( + "StoreBackEnd/pkg/protocol" + "StoreBackEnd/pkg/utils" + "bufio" + "fmt" + "strconv" +) + +// RetrieveOkRulePrefix Rule command prefix +const RetrieveOkRulePrefix = "RETRIEVE_OK" + +// RetrieveOkRule Storage structure for the RetrieveOkRule +type RetrieveOkRule struct { + // cmd Rule name + cmd string + // matcher Allow to make a regex match + matcher *protocol.RegexMatcher + // storagePath Chemin de stockage du fichier + storagePath string +} + +// CreateRetrieveOkRule Creating an instance of RetrieveOkRule +func CreateRetrieveOkRule(pattern string, storagePath string) protocol.IProtocolWriter { + return &RetrieveOkRule{ + cmd: RetrieveOkRulePrefix, + matcher: protocol.CreateRegexMatcher(pattern), + storagePath: storagePath, + } +} + +// GetCmd retrieve the command name. +func (rule RetrieveOkRule) GetCmd() string { + return rule.cmd +} + +// Execute the Rule with a string command. +func (rule RetrieveOkRule) Execute(argsData ...string) *protocol.ProtocolWriterResult { + buildedCmd, _ := rule.matcher.Build(RetrieveOkRulePrefix, argsData...) + + return &protocol.ProtocolWriterResult{ + Cmd: buildedCmd, + Write: func(writer *bufio.Writer) { + fileSize, _ := strconv.Atoi(argsData[1]) + rule.onWrite(writer, argsData[0], fileSize) + }, + } +} + +func (rule RetrieveOkRule) onWrite(writer *bufio.Writer, hashFileName string, fileSize int) { + path := fmt.Sprintf("%s/%s", rule.storagePath, hashFileName) + if utils.SendFile(path, fileSize, writer) { + println("Fichier envoyé au client") + } else { + println("Fichier non-envoyé au client") + } +} diff --git a/pkg/utils/FileReceiver.go b/pkg/utils/FileReceiver.go index fc4e075..aaac2fe 100644 --- a/pkg/utils/FileReceiver.go +++ b/pkg/utils/FileReceiver.go @@ -44,11 +44,3 @@ func copyFile(currentSize int, fileSize int, reader *bufio.Reader, buffer []byte } return false, false } - -func fileExists(filename string) bool { - info, err := os.Stat(filename) - if os.IsNotExist(err) { - return false - } - return !info.IsDir() -} diff --git a/pkg/utils/FileSender.go b/pkg/utils/FileSender.go index fe33016..2609c91 100644 --- a/pkg/utils/FileSender.go +++ b/pkg/utils/FileSender.go @@ -8,9 +8,9 @@ import ( ) // SendFile Envoie d'un fichier local sur le réseau -func SendFile(fileName string, fileSize int, writer *bufio.Writer) bool { +func SendFile(filePath string, fileSize int, writer *bufio.Writer) bool { // Ouverture du fichier - file, fileErr := os.Open(fmt.Sprintf("/home/benjamin/sbe/%s", fileName)) + file, fileErr := os.Open(fmt.Sprintf("%s", filePath)) if fileErr != nil { return false } @@ -25,5 +25,5 @@ func SendFile(fileName string, fileSize int, writer *bufio.Writer) bool { return false } - return false + return true } diff --git a/pkg/utils/Hasher.go b/pkg/utils/Hasher.go index 3178285..36e03b2 100644 --- a/pkg/utils/Hasher.go +++ b/pkg/utils/Hasher.go @@ -10,6 +10,12 @@ import ( ) func HashFileCompare(path string, fingerPrint string) bool { + sum := GenFingerPrint(path) + + return fingerPrint == fmt.Sprintf("%x", sum) +} + +func GenFingerPrint(path string) []byte { f, err := os.Open(path) if err != nil { log.Fatal(err) @@ -24,8 +30,5 @@ func HashFileCompare(path string, fingerPrint string) bool { } sum := hash.Sum(nil) - fmt.Printf("%x\n", sum) - - println(fingerPrint, fmt.Sprintf("%x", sum)) - return fingerPrint == fmt.Sprintf("%x", sum) + return sum } diff --git a/pkg/utils/Network.go b/pkg/utils/Network.go index 607d42c..a8ceddc 100644 --- a/pkg/utils/Network.go +++ b/pkg/utils/Network.go @@ -1,6 +1,7 @@ package utils import ( + "errors" "fmt" "net" "strings" @@ -29,6 +30,26 @@ func NetworkLister() { print("\n") } +// RetrieveIPv4FromInterface Retrieve the first IPv4 from an interface. +func RetrieveIPv4FromInterface(inter string) (net.IP, error) { + ief, err := net.InterfaceByName(inter) + addrs, err := ief.Addrs() + if err != nil { + return nil, err + } + for _, addr := range addrs { + switch v := addr.(type) { + case *net.IPNet: + //if !v.IP.IsLoopback() { + if v.IP.To4() != nil { //Verify if IP is IPV4 + return v.IP, nil + } + //} + } + } + return nil, errors.New("no IPv4 found") +} + // IsIPv4 Check if the ip is a v4 or v6 ip func IsIPv4(addr string) bool { return strings.Count(addr, ":") < 2 diff --git a/resources/AppConfig.json b/resources/AppConfig.json index 38b0daf..7d5b169 100644 --- a/resources/AppConfig.json +++ b/resources/AppConfig.json @@ -1,8 +1,8 @@ { - "multicastNetworkInterface": "Wi-Fi", - "multicastAddress": "224.66.66.1:15502", - "multicastSecond": 30, - "domain": "lightcontainerSB01", - "unicastPort": 58000, - "storagePath": "/home/benjamin/sbe" + "multicastNetworkInterface" : "Loopback Pseudo-Interface 1", + "multicastAddress" : "224.66.66.1:15502", + "multicastSecond" : 30, + "domain" : "lightcontainerSB01", + "unicastPort" : 58000, + "storagePath" : "D:\\sbe" } \ No newline at end of file