// This handler receive the incoming connections from the storages func (m *Bridger) serverReceptioner(storageConn *ws.MyConn) bool { // Get the user Id id := context.Get(storageConn.HttpRequest, "userId").(int64) // Check if another storage is already connected _, connected := m.storages[id] storageConn.SendEvent(ws.Event{ Name: "initialization", Data: map[string]bool{ "success": !connected, }, }) if connected { return false } // Create the storage manager storage := Storage{ // Ws connection to the storage ws: storageConn, // Lock for the clients array clientLock: &sync.Mutex{}, // Map of the clients connected to this sotrage clients: make(map[Client]bool), // Shutdow channel shutdown: make(chan (bool)), } storageConn.SetListener(func(event ws.Event) { if event.Name == "_error" { // Lock the array storage.clientLock.Lock() // Notify this error to all the clients of this storage for client := range storage.clients { client.ws.SendEvent(ws.Event{ Name: "storageInfo", Data: map[string]bool{"connected": false}, }) // TODO: add a function to close the client, not close the // raw socket! client.ws.Close() } // Unlock the array storage.clientLock.Unlock() // And then remove the storage from the storages map delete(m.storages, id) return } // Repeat this event to all the clients for client, _ := range storage.clients { client.ws.SendEvent(event) } }) // Once that i'm sure of the hidentity of the server, let's add // to the servers map. m.storages[id] = &storage // Return a nil because no informations need to be attached to this connection // (i dunno why i have created this info, and probably i'll remove the connection info // soon), and a true that means that this conenction is a good ione and shouldn't be // closed return true }
// This method is called when a new ws connection is made by a client. // This method check if the user is authorized and create a new struct that describe // the user. func (m *Bridger) clientReceptioner(clientConn *ws.MyConn) bool { // Get the user Id id := context.Get(clientConn.HttpRequest, "userId").(int64) // Check if the storage of this user is conencted storage, connected := m.storages[id] // Send the storage connection state clientConn.SendEvent(ws.Event{ Name: "storageInfo", Data: map[string]bool{ "connected": connected, }, }) // If the storage is not connected, close the connections of this client if !connected { // Return false, that means close the ws connection return false } // Create a new client object client := Client{ ws: clientConn, } // Lock the array storage.clientLock.Lock() // Add the client to the map of clients of this storage storage.clients[client] = true // Unlock the array storage.clientLock.Unlock() clientConn.SetListener(func(event ws.Event) { if event.Name == "_error" { // In this case the client is disconnected fmt.Println("Client disconnected") // So remove it from the clients array in the storage struct // Lock the mutex of the map storage.clientLock.Lock() // Remove from the array delete(storage.clients, client) // Unlock the mutex of the map storage.clientLock.Unlock() return } if event.QueryId != "" { storage.ws.MakeAsyncQuery(event, func(data interface{}) { response := ws.Event{ QueryId: event.QueryId, Name: "queryResponse", Data: data, } clientConn.SendEvent(response) }) return } // Redirect the event to the storage err := storage.ws.SendEvent(event) if err != nil { // TODO: handle this kind of error fmt.Println("Error proxying message to storage") } }) // keep the connection and don't add any info return true }