// Writes data to the socket of the specified connection func sendOut(user *Admin, query map[string]interface{}) error { enc := bencode.NewEncoder() enc.Encode(query) _, err := io.WriteString(user.Conn, string(enc.Bytes)) if err != nil { return err } return nil }
func SendCmd(user *Admin, cmd string, args map[string]interface{}) (response map[string]interface{}, err error) { query := make(map[string]interface{}) enc := bencode.NewEncoder() // Generate a unique transaction ID for this request. // This tells Reader which channel to send the data back to us on. txid := strconv.FormatInt(rand.Int63(), 10) //randInt(10, 15) query["txid"] = txid // Check if we need to use authentication for this command. if cmd == "ping" || cmd == "cookie" { query["q"] = cmd } else { //Request a cookie cookie, err := ReqCookie(user) if err != nil { return nil, err } query["q"] = "auth" query["aq"] = cmd query["cookie"] = cookie if args != nil { query["args"] = args } //Generate the first hash we need query["hash"] = sha256hash(user.Password + cookie) //Encode the query and get the final hash enc.Encode(query) data := string(enc.Bytes) query["hash"] = sha256hash(data) } //Re-encode the query with the new hash enc = bencode.NewEncoder() enc.Encode(query) // If we are telling cjdns to exit, then we will not get a response, so there is no need to wait if cmd != "Core_exit" { //create the channel to receive data back on rChan := make(chan map[string]interface{}, 1) // use buffered channel to avoid blocking reader. user.Mu.Lock() user.Channels[txid] = rChan user.Mu.Unlock() // remove channel from map no matter how this function exits. defer func() { user.Mu.Lock() delete(user.Channels, txid) user.Mu.Unlock() }() //Send the query _, err = io.WriteString(user.Conn, string(enc.Bytes)) if err != nil { return nil, err } output, ok := <-rChan if !ok { return nil, fmt.Errorf("Socket closed") } // If an error field exists, and we have an error, return it if _, ok := response["error"]; ok { if response["error"] != "none" { err = fmt.Errorf(response["error"].(string)) return } } return output, nil } //Send the query _, err = io.WriteString(user.Conn, string(enc.Bytes)) if err != nil { return nil, err } return make(map[string]interface{}), nil }