Browse Source

Adding sources and initial methods

master
DanB 10 years ago
parent
commit
02654dd7b8
3 changed files with 167 additions and 1 deletions
  1. +4
    -1
      README.md
  2. +115
    -0
      kamjsonrpc.go
  3. +48
    -0
      kamjsonrpc_local_test.go

+ 4
- 1
README.md View File

@ -1,2 +1,5 @@
# kamjsonrpc
JSON-RPC client for Kamailio
Simple JSON-RPC client for Kamailio
See local_test file for usage.

+ 115
- 0
kamjsonrpc.go View File

@ -0,0 +1,115 @@
/*
Released under MIT License <http://www.opensource.org/licenses/mit-license.php
Copyright (C) ITsysCOM GmbH. All Rights Reserved.
Provides simple Kamailio JSON-RPC over HTTP communication.
*/
package kamjsonrpc
import (
"bytes"
"crypto/tls"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"sync"
)
type KamJsonRpcRequest struct {
Jsonrpc string `json:"jsonrpc"`
Method string `json:"method"`
Params []interface{} `json:"params"`
Id uint64 `json:"id"`
}
type KamJsonRpcResponse struct {
Jsonrpc string `json:"jsonrpc"`
Id uint64 `json:"id"`
Result *json.RawMessage `json:"result"`
Error error `json:"error"`
}
func NewKamailioJsonRpc(url string, skipTlsVerify bool) (*KamailioJsonRpc, error) {
client := &http.Client{Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: skipTlsVerify}}}
return &KamailioJsonRpc{url: url, client: client, mutex: new(sync.Mutex)}, nil
}
type KamailioJsonRpc struct {
url string
client *http.Client
id uint64
mutex *sync.Mutex
}
// Generic function to remotely call a method and pass the parameters
func (self *KamailioJsonRpc) Call(serviceMethod string, args interface{}, reply *json.RawMessage) error {
self.mutex.Lock()
reqId := self.id
self.id += 1
self.mutex.Unlock()
req := &KamJsonRpcRequest{Jsonrpc: "2.0", Method: serviceMethod, Id: reqId}
if argSlice, isSlice := args.([]string); isSlice {
req.Params = make([]interface{}, len(argSlice))
for idx, val := range argSlice {
req.Params[idx] = val
}
} else {
req.Params = []interface{}{args}
}
body, err := json.Marshal(req)
if err != nil {
return err
}
resp, err := self.client.Post(self.url, "application/json", bytes.NewBuffer(body))
if err != nil {
return err
}
defer resp.Body.Close()
respBody, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}
var kamResponse KamJsonRpcResponse
if err = json.Unmarshal(respBody, &kamResponse); err != nil {
return err
}
if kamResponse.Error != nil {
return kamResponse.Error
}
if resp.StatusCode > 299 {
return fmt.Errorf("Unexpected status code received: %d", resp.StatusCode)
}
if kamResponse.Id != reqId {
return fmt.Errorf("Unsynchronized request, had: %d, received: %d", reqId, kamResponse.Id)
}
*reply = *kamResponse.Result
return nil
}
// Add inidividual methods over the generic one
type RegistrationInfo struct {
LocalUuid string `json:"l_uuid"`
LocalUsername string `json:"l_username"`
LocalDomain string `json:"l_domain"`
RemoteUsername string `json:"r_username"`
RemoteDomain string `json:"r_domain"`
Realm string `json:"realm"`
AuthUsername string `json:"auth_username"`
AuthPassword string `json:"auth_password"`
AuthProxy string `json:"auth_proxy"`
Expires int64 `json:"expires"`
Flags int64 `json:"flags"`
DiffExpires int64 `json:"diff_expires"`
TimerExpires int64 `json:"timer_expires"`
}
func (self *KamailioJsonRpc) UacRegInfo(params []string, reply *RegistrationInfo) error {
var regRaw json.RawMessage
if err := self.Call("uac.reg_info", params, &regRaw); err != nil {
return err
}
return json.Unmarshal(regRaw, reply)
}

+ 48
- 0
kamjsonrpc_local_test.go View File

@ -0,0 +1,48 @@
package kamjsonrpc
import (
"encoding/json"
"flag"
"reflect"
"testing"
)
var testLocal = flag.Bool("local", false, "Perform the tests only on local test environment, not by default.") // This flag will be passed here via "go test -local" args
var kamAddr = flag.String("kam_addr", "http://127.0.0.1:5060", "Address where to reach kamailio http server")
var kamRpc *KamailioJsonRpc
func TestKamJsonRpcConn(t *testing.T) {
if !*testLocal {
return
}
var err error
if kamRpc, err = NewKamailioJsonRpc(*kamAddr, true); err != nil {
t.Fatal("Cannot connect to kamailio:", err)
}
}
func TestKamJsonRpcCall(t *testing.T) {
if !*testLocal {
return
}
var reply json.RawMessage
if err := kamRpc.Call("uac.reg_info", []string{"l_uuid", "unknown"}, &reply); err != nil {
t.Error(err)
} else if reflect.DeepEqual(reply, json.RawMessage{}) {
t.Error("Empty reply")
}
}
func TestKamJsonRpcUacRegInfo(t *testing.T) {
if !*testLocal {
return
}
var eReply RegistrationInfo
var reply RegistrationInfo
if err := kamRpc.UacRegInfo([]string{"l_uuid", "unknown"}, &reply); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(reply, eReply) {
t.Errorf("Expecting: %+v, received: %+v", eReply, reply)
}
}

Loading…
Cancel
Save