// Registra l'utente nel server come nuovo utente func (client *Client) registrati() error { logs.Log("registrazione nuovo utente") username, err := client.stream.ReadString('\\') if err != nil { return NewErrorLogin(client, "Errore nel leggere lo username\n\tmotivo: "+err.Error()) } username = strings.Trim(username, "\\") password, err := client.stream.ReadString('\\') if err != nil { return NewErrorLogin(client, "Errore nel leggere la password\n\tmotivo: "+err.Error()) } password = strings.Trim(password, "\\") var success bool client.user, success = database.Data.RegisterNewUser(username, password) if !success { return NewErrorLogin(client, "impossibile registrare nuovo utente") } logs.Log("Registrato nuovo utente: ", username, " password: "******"\\R0\\") client.stream.Flush() return nil }
// Fa il flush sul database di tutti i post relativi alla conversazione func (conv *Conversation) salvaTuttiIPostSQL(data *DatabaseRegistration) error { messaggio := "salvataggio di tutti i post sul database" logs.Log(messaggio) err := conv.testaPost.salvaPostRicSQL(conv, data) if err != nil { logs.Error(messaggio + " fallito") } else { logs.Log(messaggio + " riuscito") } return err }
// Inizializza tutte le operazioni necessarie per sul database func init() { logs.Log("init del database") ServerFakeUser = new(User) ServerFakeUser.ID = 0 ServerFakeUser.Username = "******" serverPassword := sha256.New() serverPassword.Write([]byte("toor")) ServerFakeUser.password = serverPassword.Sum([]byte{}) err := CreateDataBaseSQL() if err != nil { logs.Error(err.Error()) } // MainConv = NewConversation(ServerFakeUser) err = Data.caricaConversazioni() if err != nil { logs.Error("Impossibile caricare le conversazioni vecchie\nmotivo: ", err.Error()) } // err = salvaUtente(ServerFakeUser) // if err != nil { // logs.Error("Impossibile salvare l'utente server nel database\nmotivo: ", err.Error()) // }() Data.CaricaUtentiSQL() if err != nil { logs.Error("Impossibile caricare gli utenti dal database\nmotivo: ", err.Error()) } go func() { var spegniti bool = false logs.AggiungiAzioneDiChiusura(func() { spegniti = true }) tk := time.NewTicker(10 * time.Minute) for !spegniti { <-tk.C err := MainConv.salvaTutteLeConversazioniSQL() if err != nil { logs.Error("Impossibile salvare tutti i post\nmotivo: ", err.Error()) } logs.Log("salvate tutte le conversazioni sul database") //err := MainConv.salvaTuttiIPostSQL(&Data) //if err != nil { // logs.Error("Impossibile salvare tutti i post\nmotivo: ", err.Error()) //} } tk.Stop() }() }
// Carica le conversazioni dal database. Da utilizzare all'avvio del server // // BUG: carica tutte le conversazioni tiene il puntatore solo dell'ultima // in MainConv func (datab *DatabaseRegistration) caricaConversazioni() error { rows, err := db.Query("SELECT * FROM conversation") if err != nil { return err } logs.Log("caricamento conversazioni") for ; rows.Next(); datab.contatore++ { var conversationID int err := rows.Scan(&conversationID) if err != nil { return err } MainConv = new(Conversation) MainConv.ID = conversationID MainConv.connected = make(map[int]*convUser) MainConv.postMap = make(map[int]*Post) MainConv.contatorePost = 0 err = MainConv.caricaPost() if err != nil { return err } fmt.Println("caricata conversazione:", conversationID) } return nil }
// Carica tutti gli utenti dal database nella memoria principale func (datab *DatabaseRegistration) CaricaUtentiSQL() error { rows, err := db.Query("SELECT * FROM t_user") if err != nil { return err } logs.Log("caricamento utenti") for ; rows.Next(); datab.contatore++ { var username string var userID int var password string err := rows.Scan(&userID, &username, &password) if err != nil { return err } username = strings.TrimSpace(username) password = strings.TrimSpace(password) user := new(User) user.Username = username user.ID = userID user.password = []byte(password) fmt.Println("caricato vecchio utente: ", username, " ID: ", strconv.Itoa(userID), "\npassword: ", password) datab.userNameToId[username] = user datab.userIDtoUser[userID] = user } return nil }
// carica in memoria tutti i post della conversazione dal database func (conv *Conversation) caricaPost() error { query, err := db.Prepare("SELECT id,father,text,first_response,second_response FROM post WHERE conversation = $1") if err != nil { return err } rows, err := query.Query(conv.ID) if err != nil { return err } parentPostMap := make(map[int]*Post) firSonPostMap := make(map[int]*Post) secSonPostMap := make(map[int]*Post) logs.Log("caricamento post della conversazione ", strconv.Itoa(conv.ID)) for ; rows.Next(); conv.contatorePost++ { var id, parent, first_response, second_response int var text string err := rows.Scan(&id, &parent, &text, &first_response, &second_response) if err != nil { return err } post := new(Post) post.idPost = id post.testo = NewSuperString() post.testo.InsStringElem(text, 0) conv.postMap[id] = post post.writers = list.New() if id == 0 { conv.testaPost = post } parentPostMap[parent] = post firSonPostMap[first_response] = post secSonPostMap[second_response] = post fmt.Println("caricato vecchio post: ", strconv.Itoa(id), "\ntesto: ", text) } for k, post := range parentPostMap { post.padre = conv.postMap[k] } for k, post := range firSonPostMap { post.rispostaPrincipale = conv.postMap[k] } for k, post := range secSonPostMap { post.rispostaSecondaria = conv.postMap[k] } return nil }
// Inizializzare il server in ascolto per le Sincronizzazione delle conversazioni // // "laddress string" indica su quali indirizza ascoltare e su quale porta func StartServer(laddress string) { ln, err := net.Listen("tcp", laddress) logs.Log("Server in ascolto su: \"", laddress, "\"") if err != nil { logs.Error("Errore nell'aprire la connessione: ", err.Error()) return //TODO handle error } //database.MainConv = database.NewConversation(database.ServerFakeUser) //duplicato! //canale := make(chan byte, 256) codaReadiness := make(chan *Client, 64) codaAccettazioni := make(chan *Client, 64) logs.AggiungiAzioneDiChiusura(func() { close(codaReadiness) close(codaAccettazioni) }) go spedisci(codaAccettazioni, codaReadiness) var spegniti bool = false logs.AggiungiAzioneDiChiusura(func() { spegniti = true ln.Close() }) for !spegniti { conn, err := ln.Accept() if spegniti { return } if err != nil { //TODO fare un pacchetto per la raccolta degli errori logs.Error("Tentativo di connessione non andato a buon fine: ", err.Error()) } go func() { client, gestore := GestisciClient(conn) if client != nil { go gestore(codaReadiness) codaAccettazioni <- client } else { //L'handshaking non è andato a buon fine conn.Close() } }() } }
// Esegue il login del client (registra lo stato online func (client *Client) login() error { logs.Log("login nuovo utente") username, err := client.stream.ReadString('\\') if err != nil { return NewErrorLogin(client, "Errore nel leggere lo username\n\tmotivo: "+err.Error()) } username = strings.Trim(username, "\\") //CONTROLLO SE L'UTENTE È GIÀ REGISTRATO var newuser bool client.user, newuser = database.Data.ConnectUser(username) if newuser { err := NewErrorLogin(client, "connessione impossibile: Utente non registrato!") client.stream.WriteString("\\R1\\") client.stream.Flush() return err } logs.Log("IP:", (*client.conn).RemoteAddr().String(), " USERNAME:"******" UserID:", strconv.Itoa(client.user.ID)) //RICHIESTA PASSWORD password, err := client.stream.ReadString('\\') if err != nil { return NewErrorLogin(client, "Errore nel leggere la password\n\tmotivo: "+err.Error()) } password = strings.Trim(password, "\\") if !client.user.VerifyPassword(password) { return NewErrorLogin(client, username+" Password errata") } logs.Log("Login riuscito di ", username, " da ", (*client.conn).RemoteAddr().String()) client.stream.WriteString("\\R0\\") client.stream.Flush() return nil }
// crea il post dentro il database. Ogni post deve essere creato prima di // potere essere salvato. func (datab *DatabaseRegistration) creaPostSQL(conv *Conversation, post *Post) error { logs.Log("creo post ", strconv.Itoa(post.idPost)) var idPadre, idRPri, idRSec int = -1, -1, -1 if post.padre != nil { idPadre = post.padre.idPost } if post.rispostaPrincipale != nil { idRPri = post.rispostaPrincipale.idPost } if post.rispostaSecondaria != nil { idRSec = post.rispostaSecondaria.idPost } _, err := insertPostOp.Exec(post.idPost, conv.ID, post.testo.GetComplete(false), idPadre, idRPri, idRSec) if err != nil { logs.Error("Impossibile creare il post ", strconv.Itoa(post.idPost), " nel database") return err } return nil }