func NewClient() *Conn { conn := Conn{ ClientId: random.Letters(20), Ready: make(chan bool, 1), } conn.Ready <- true return &conn }
// CheckCallsWaiting checks to see if there are any callers available to make // the calls waiting to be called func (o *Operator) CheckCallsWaiting() { log.Println("Checking for calls waiting...") log.Println(o.CallsWaiting, o.CallersReady) // If there are no calls waiting to be made there is nothing to do if len(o.CallsWaiting) < 1 { return } // There are no callers ready so there is nothing we can do if len(o.CallersReady) < 1 { return } // Grab a random caller var callerID string var caller *websocket.Conn for id, callerWs := range o.CallersReady { callerID = id caller = callerWs // Grab one and exit the loop break } // The caller should be removed from the ready state becase it will now be // in the in_call state delete(o.CallersReady, callerID) // The call we are about to make will no longer waiting to be made and // therefore needs to be removed from the waiting slice makeCall, callsWaiting := o.CallsWaiting[0], o.CallsWaiting[1:] o.CallsWaiting = callsWaiting // Take the caller we just removed from ready and put them in the make_call // state for the number we just removed from CallsWaiting log.Println("About to have", callerID, "call", makeCall.Number) websocket.JSON.Send(caller, CallerMessage{ State: "make_call", Number: makeCall.Number, }) // We need a way to end the call so take the caller and put them in the // CallersInCall map, the key to access it will be a randomly generated // lock which the client will get back in case they want to end the call. // If the client never ends the call then EndCallTimeout will occor and the // call will be ended // Create the lock log.Println("Creating lock for", makeCall.Number, "...") lock := random.Letters(10) log.Println("Status make_call has been sent to", callerID, "for number", makeCall.Number, "with lock", lock, ) // Put the caller in the CallersInCall map by that lock o.CallersInCall[lock] = caller // Start the timeout in case the client does not end the call go o.EndCallTimeout(lock, o.Timeout) // Return the lock to the client that requested this call in case they want // to end it before the timeout makeCall.Lock <- lock }
// CallerHandler handles callers connecting via websocket func CallerHandler(ws *websocket.Conn) { // Generate a random callerID so that it can be removed if it disconnects callerID := random.Letters(10) log.Println("Caller connected", callerID) // Receive message from the caller for { var message CallerMessage err := websocket.JSON.Receive(ws, &message) if err == io.EOF { ws.Close() // Make sure the operator knows that the caller has disconnected Op.CallerDisconnected <- callerID log.Println("Caller disconnected", callerID) return } else if err != nil { log.Println("Error receiving from callerID", callerID, ":", err) return } else { // Echo back err := websocket.JSON.Send(ws, message) if err != nil { log.Println("Error sending to callerID", callerID, ":", err) return } // Preform actions based on state switch message.State { case StateNotReady: // Send it the login info websocket.JSON.Send(ws, map[string]string{ "set": "gmail_username", "value": viper.GetString("gmail_username"), }) websocket.JSON.Send(ws, map[string]string{ "set": "gmail_password", "value": viper.GetString("gmail_password"), }) // Tell it that it has the login info websocket.JSON.Send(ws, map[string]string{ "state": StateHasLoginInfo, }) case StateReady: // If its ready then the operator needs to know that callerReadyMessage := &CallerReadyMessage{ ID: callerID, Ws: ws, } Op.CallerReady <- callerReadyMessage } } } }
func (client *Client) CreateChannel(key ...string) string { ChannelKey := random.Letters(10) if len(key) > 0 && key[0] != "" { ChannelKey = key[0] } // Allocate a channel so we know when all data has been received _, ok := client.Channels[ChannelKey] // Delete it if it already exists if ok { delete(client.Channels, ChannelKey) } // Make the channel client.Channels[ChannelKey] = make(chan string, 100) return ChannelKey }
func TestClientSendRecv(t *testing.T) { conf := config.Load() correctResponse := make(chan int) randString := random.Letters(50) ws := NewClient() ws.Recv = checkMessage(randString, correctResponse) wsUrl := fmt.Sprintf("http://%s:%s/ws", conf.Host, conf.Port) err := ws.Connect(wsUrl) if err != nil { log.Println(err) } go ws.Read() log.Println("Waiting for correctResponse", randString) ws.Write([]byte(randString)) <-correctResponse log.Println("Got correctResponse", randString) }
func TestServiceCallMethod(t *testing.T) { conf := config.Load() correctResponse := make(chan int) randString := random.Letters(25) service := NewTestService() service.ShouldBe = randString service.CorrectResponse = correctResponse // service.Methods = map[string]func(interface{}, []byte){ // "TestServiceMessage": checkResponse, // } wsUrl := fmt.Sprintf("http://%s:%s/ws", conf.Host, conf.Port) err := service.Connect(wsUrl) if err != nil { log.Println(err) } go service.Read() log.Println("Waiting for correctResponse", randString) checkJson := fmt.Sprintf("{\"data\": \"%s\", \"method\": \"TestServiceMessage\"}", randString) service.Write([]byte(checkJson)) <-correctResponse log.Println("Got correctResponse", randString) }
func TestStorageDump(t *testing.T) { config.ConfigSet() wsUrl := fmt.Sprintf( "http://%s:%s/ws", viper.GetString("host"), viper.GetString("port"), ) log.Println("Connecting to", wsUrl) // Set up the storage service storage := NewStorage() err := storage.Connect(wsUrl) if err != nil { log.Println(err) } go storage.Read() // Set up the client clientTest := client.NewClient() err = clientTest.Connect(wsUrl) if err != nil { log.Println(err) } go clientTest.Read() // The number of items to save numSaved := 5 // Populate the storage.Data for index := 0; index < numSaved; index++ { item := map[string]interface{}{ "Id": random.Letters(5), } clientTest.Save(item) } // Get all of the data in storeage savedData := clientTest.AllData() // if numSaved != len(savedData) { // panic("All of the items we sent weren't saved!!") // } log.Println(savedData) }