/// <summary>
        /// La funzione deve gestire la creazione di un nuovo file.
        /// </summary>
        public override bool Handle()
        {
            if(this.Stopped)
                return false;

            if (String.IsNullOrEmpty(base.FullPath)){
                throw new Exception("Path e nome del file non validi.");
            }
            using(TcpClient connection = new TcpClient()){
                connection.Connect(UserCredentials.Instance.Host, UserCredentials.Instance.Port);
                using (StreamReader sr = new StreamReader(connection.GetStream()))
                using (StreamWriter sw = new StreamWriter(connection.GetStream()))
                {
                    //sr.BaseStream.ReadTimeout = 10000;
                    //sw.BaseStream.WriteTimeout = 10000;

                    /************************************ Inizio della funzione ***************************************/

                    string username = UserCredentials.Instance.Username;
                    string accesstoken = UserCredentials.Instance.AccessToken;
                    string allPath = this.FullPath;
                    string subcmd = ProtocolStrings.SUBCMD_CREATE_MODIFY;
                    long client_vfsversion  = SyncToken.Instance.VFSVersion;

                    try
                    {
                        string syncroPath = UserUtils.GetRootPath();
                        if (!allPath.StartsWith(syncroPath))
                            throw new Exception("File o root non validi.");
                        string relativePath = allPath.Replace(syncroPath, "/");

                        //controlli
                        if (String.IsNullOrEmpty(username) || String.IsNullOrEmpty(accesstoken))
                        {
                            throw new Exception("Lo username o l'accesstoken non può essere nullo.");
                        }
                        if (!relativePath.StartsWith("/"))
                        {
                            throw new Exception("Il path deve iniziare con uno slash.");
                        }

                        if (!File.Exists(allPath))
                        {
                            throw new Exception("Il path assoluto non esiste in questo file system");
                        }
                        string name = Path.GetFileName(relativePath);
                        string path = Path.GetDirectoryName(relativePath).TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar;
                        DateTime lastUpdate = File.GetLastWriteTime(allPath);

                        FileInfo file = new FileInfo(allPath);
                        long dim = file.Length;

                        string hashFile = UserUtils.GetFileHash(allPath);

                        if (String.IsNullOrEmpty(name) || name.StartsWith("\\"))
                        {
                            throw new Exception("Il nome del file non può essere nullo e non può iniziare con uno slash.");
                        }
                        if (String.IsNullOrEmpty(hashFile))
                        {
                            throw new Exception("L'hash del file non può essere vuoto o nullo.");
                        }
                        if (dim < 0)
                        {
                            throw new Exception("La dimensione del file non può essere negativa.");
                        }

                        long nchunkUser = (long)Math.Ceiling(((double)file.Length / (double)ProtocolStrings.CHUNK_SIZE));

                        if (nchunkUser < 0)
                        {
                            throw new Exception("Il numero di chunk  del file non può essere negativo.");
                        }
                        //la lista di chunk da inviare al server
                        List<VChunk> listChunk = new List<VChunk>();

                        PushFile_D pD = null;

                        //primo controllo da fare
                        if (this.Stopped)
                            return false;

                        //apro il file e calcolo il numero di chunk
                        using (FileStream fs = new FileStream(allPath, FileMode.Open, FileAccess.Read, FileShare.Delete))
                        {
                            byte[] c = new byte[ProtocolStrings.CHUNK_SIZE];
                            string hashChunk;
                            VChunk vc = null;
                            for (long i = 0; i < nchunkUser; i++)
                            {
                                if (this.Stopped)
                                    return false;
                                int l = fs.Read(c, 0, c.Count());
                                hashChunk = UserUtils.GetHash(c, l);
                                vc = new VChunk(i, -1, -1, hashChunk, l, lastUpdate);
                                listChunk.Add(vc);
                            }

                            if (this.Stopped)
                                return false;

                            //invio la richiesta
                            PushFile_A req = new PushFile_A(username, accesstoken, subcmd, name, path, lastUpdate, hashFile, dim, nchunkUser, client_vfsversion, listChunk);
                            UserUtils.NetworkWriteLine(sw, req.ToJSON());

                            //attendo la risposta del server
                            string rec = UserUtils.NetworkReadLine(sr);
                            Response r = Response.fromJson(rec);
                            if (r.Result == 401)
                            {
                                //problemi con la login T (token)
                                throw new UserLoginException(BadLoginResponse.fromJson(rec).Msg);
                            }
                            else if (r.Result != 200)
                            {
                                throw new Exception(BadPushFileResponse.fromJson(rec).Msg);
                            }

                            if (this.Stopped)
                                return false;

                            PushFile_Abis pAbis = PushFile_Abis.fromJson(rec);

                            //ora il server mi deve mandare la lista di chunk che gli devo inviare
                            //N.B. se la lista è vuota devo andare direttamente all'ultima operazione.
                            if (pAbis.NChunk > 0)
                            {
                                PushFile_B pB = null;
                                byte[] filledChunk = new byte[ProtocolStrings.CHUNK_SIZE];
                                long id = -1;
                                fs.Seek(0, SeekOrigin.Begin);

                                do
                                {
                                    if (this.Stopped)
                                        return false;

                                    pB = PushFile_B.fromJson(UserUtils.NetworkReadLine(sr));
                                    id = pB.IdChunk;
                                    fs.Seek(id * (ProtocolStrings.CHUNK_SIZE), SeekOrigin.Begin);
                                    int l = fs.Read(filledChunk, 0, (int)ProtocolStrings.CHUNK_SIZE);
                                    //TODO con l'ultimo chunk sprechiamo byte(inviamo byte inutili).
                                    PushFile_C pC = new PushFile_C(filledChunk, l);
                                    UserUtils.NetworkWriteLine(sw, pC.toJSON());

                                } while (!pB.Done);
                            }
                            pD = PushFile_D.fromJson(UserUtils.NetworkReadLine(sr));
                            /** N.B. da qui in poi non dobbiamo più stoppare il thread perché il server ha committato **/
                        }
                        //ora devo andare a salvare il synctoken (che poi sarebbe il vfsversion)
                        SyncToken.Instance.VFSVersion = pD.NewVfsversion;

                    }
                    catch (SocketException e)
                    {
                        throw new NetworkException("Si è verificato un errore di rete.", e);
                    }
                    catch (UserLoginException e)
                    {
                        throw e;
                    }
                    catch (IOException e) {
                        if ((uint)e.HResult == FILE_IN_USE)
                        {
                            throw new FileInUseException("Il file è in uso da un altro processo, verrà gestito più tardi.");
                        }
                    }
                    catch (Exception e)
                    {
                        throw new PushFileExceptionU(e.Message);
                    }

                    /**************************************** Fine della funzione ***************************************/
                }

            }
            return true;
        }
예제 #2
0
        public static long DoPushFile(string username, string accesstoken, string allPath, string subcmd, long client_vfsversion, StreamWriter sw, StreamReader sr)
        {
            try
            {
                string syncroPath = GetRootPath();
                if (!allPath.StartsWith(syncroPath))
                    throw new Exception("File o root non validi.");
                string relativePath = allPath.Replace(syncroPath, "/");

                //controlli
                if(String.IsNullOrEmpty(username) || String.IsNullOrEmpty(accesstoken)){
                    throw new Exception("Lo username o l'accesstoken non può essere nullo.");
                }
                if (!relativePath.StartsWith("/"))
                {
                    throw new Exception("Il path deve iniziare con uno slash.");
                }

                File.Exists(allPath);
                string name = Path.GetFileName(relativePath);
                string path = Path.GetDirectoryName(relativePath);
                path = path.TrimEnd(Path.DirectorySeparatorChar);
                path += Path.DirectorySeparatorChar;

                DateTime lastUpdate = File.GetLastWriteTime(allPath);

                FileInfo file = new FileInfo(allPath);
                long dim = file.Length;

                string hashFile = GetFileHash(allPath);

                if(String.IsNullOrEmpty(name) || name.StartsWith("\\")){
                    throw new Exception("Il nome del file non può essere nullo e non può iniziare con uno slash.");
                }
                if(String.IsNullOrEmpty(hashFile)){
                    throw new Exception("L'hash del file non può essere vuoto o nullo.");
                }
                if(dim<0){
                    throw new Exception("La dimensione del file non può essere negativa.");
                }

                FileInfo finfo = new FileInfo(allPath);
                long nchunkUser = (long)Math.Ceiling(((double)finfo.Length / (double)ProtocolStrings.CHUNK_SIZE));

                if(nchunkUser<0){
                    throw new Exception("Il numero di chunk  del file non può essere negativo.");
                }
                //la lista di chunk da inviare al server
                List<VChunk> listChunk = new List<VChunk>();

                PushFile_D pD = null;

                //apro il file e calcolo il numero di chunk
                using (FileStream fs = File.OpenRead(allPath))
                {
                    byte[] c = new byte[ProtocolStrings.CHUNK_SIZE];
                    string hashChunk;
                    VChunk vc = null;
                    for (long i = 0; i < nchunkUser; i++)
                    {
                        int l = fs.Read(c, 0, c.Count());
                        hashChunk = GetHash(c,l);
                        vc = new VChunk(i, -1, -1, hashChunk, l, lastUpdate);
                        listChunk.Add(vc);
                    }

                    //invio la richiesta
                    PushFile_A req = new PushFile_A(username, accesstoken, subcmd, name, path, lastUpdate, hashFile, dim, nchunkUser, client_vfsversion, listChunk);
                    NetworkWriteLine(sw, req.ToJSON());

                    //attendo la risposta del server
                    string rec = NetworkReadLine(sr);
                    Response r = Response.fromJson(rec);
                    if (r.Result == 401)
                    {
                        //problemi con la login T (token)
                        throw new UserLoginException(BadLoginResponse.fromJson(rec).Msg);
                    }
                    else if(r.Result != 200){
                        throw new Exception(BadPushFileResponse.fromJson(rec).Msg);
                    }
                    PushFile_Abis pAbis = PushFile_Abis.fromJson(rec);

                    //ora il server mi deve mandare la lista di chunk che gli devo inviare
                    //N.B. se la lista è vuota devo andare direttamente all'ultima operazione.
                    if (pAbis.NChunk > 0)
                    {
                        PushFile_B pB = null;
                        byte[] filledChunk = new byte[ProtocolStrings.CHUNK_SIZE];
                        long id = -1;
                        fs.Seek(0, SeekOrigin.Begin);

                        do
                        {
                            pB = PushFile_B.fromJson(NetworkReadLine(sr));
                            id = pB.IdChunk;
                            fs.Seek(id * (ProtocolStrings.CHUNK_SIZE), SeekOrigin.Begin);
                            int l = fs.Read(filledChunk, 0, (int)ProtocolStrings.CHUNK_SIZE);
                            //TODO con l'ultimo chunk sprechiamo byte(inviamo byte inutili).
                            PushFile_C pC = new PushFile_C(filledChunk, l);
                            NetworkWriteLine(sw, pC.toJSON());

                        } while (!pB.Done);
                    }
                    pD = PushFile_D.fromJson(NetworkReadLine(sr));
                }
                //ora devo andare a salvare il synctoken (che poi sarebbe il vfsversion)
                return pD.NewVfsversion;

            }
            catch (NetworkException e)
            {
                throw e;
            }
            catch (UserLoginException e)
            {
                throw e;
            }
            catch (Exception e)
            {
                throw new PushFileExceptionU(e.Message);
            }
        }