diff --git a/apier/.apier.go.swp b/apier/.apier.go.swp new file mode 100644 index 000000000..7fa2acbe6 Binary files /dev/null and b/apier/.apier.go.swp differ diff --git a/apier/.tpid.go.swp b/apier/.tpid.go.swp new file mode 100644 index 000000000..a511e7675 Binary files /dev/null and b/apier/.tpid.go.swp differ diff --git a/apier/apier.go b/apier/apier.go new file mode 100644 index 000000000..d9a9792de --- /dev/null +++ b/apier/apier.go @@ -0,0 +1,23 @@ +/* +Rating system designed to be used in VoIP Carriers World +Copyright (C) 2013 ITsysCOM + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see +*/ + +package apier + + +type Apier struct { +} diff --git a/apier/tpid.go b/apier/tpid.go new file mode 100644 index 000000000..1d722663d --- /dev/null +++ b/apier/tpid.go @@ -0,0 +1,43 @@ +/* +Rating system designed to be used in VoIP Carriers World +Copyright (C) 2013 ITsysCOM + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see +*/ + +package apier + +import ( + "github.com/cgrates/cgrates/utils" +) + + +type TPID struct{ + TPid string // the id of tariff plan + Active bool // Marks whether this tpid is the active one in datadb +} + + +// Return TPid associated with id queried, new tpid in case of empty id +func (self *Apier) GetTPID( reqAttr string, reply *TPID) error { + *reply = TPID{Active:false} + if reqAttr == "" { + reply.TPid = utils.NewTPid() + } else { + reply.TPid = reqAttr + } + return nil +} + + diff --git a/cmd/cgr-rater/cgr-rater.go b/cmd/cgr-rater/cgr-rater.go index 1d03e6955..e892902aa 100644 --- a/cmd/cgr-rater/cgr-rater.go +++ b/cmd/cgr-rater/cgr-rater.go @@ -30,6 +30,7 @@ import ( "github.com/cgrates/cgrates/scheduler" "github.com/cgrates/cgrates/sessionmanager" "github.com/cgrates/cgrates/utils" + "github.com/cgrates/cgrates/apier" "io" "net" "net/rpc" @@ -74,6 +75,7 @@ func listenToRPCRequests(rpcResponder interface{}, rpcAddress string, rpc_encodi rater.Logger.Info(fmt.Sprintf(" Listening for incomming RPC requests on %v", l.Addr())) rpc.Register(rpcResponder) + rpc.Register(&apier.Apier{}) var serveFunc func(io.ReadWriteCloser) if rpc_encoding == JSON { serveFunc = jsonrpc.ServeConn diff --git a/utils/coreutils.go b/utils/coreutils.go index 37999a8f0..a6f36b5a8 100644 --- a/utils/coreutils.go +++ b/utils/coreutils.go @@ -21,6 +21,8 @@ package utils import ( "crypto/sha1" "fmt" + "encoding/hex" + "crypto/rand" ) // Returns first non empty string out of vals. Useful to extract defaults @@ -38,3 +40,21 @@ func FSCgrId(uuid string) string { hasher.Write([]byte(uuid)) return fmt.Sprintf("%x", hasher.Sum(nil)) } + +func NewTPid() string { + hasher := sha1.New() + uuid,_ := GenUUID() + hasher.Write([]byte(uuid)) + return fmt.Sprintf("%x", hasher.Sum(nil)) +} + +func GenUUID() (string, error) { + uuid := make([]byte, 16) + n, err := rand.Read(uuid) + if n != len(uuid) || err != nil { + return "", err + } + uuid[8] = 0x80 + uuid[4] = 0x40 + return hex.EncodeToString(uuid), nil +} diff --git a/utils/map.go b/utils/map.go new file mode 100644 index 000000000..6dd371188 --- /dev/null +++ b/utils/map.go @@ -0,0 +1,62 @@ +/* +Rating system designed to be used in VoIP Carriers World +Copyright (C) 2013 ITsysCOM + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see +*/ + + +package utils + +// Converts map[string]string into map[string]interface{} +func ConvertMapValStrIf(inMap map[string]string) map[string]interface{} { + outMap := make(map[string]interface{}) + for field, val := range inMap { + outMap[field] = val + } + return outMap +} + +// Mirrors key/val +func MirrorMap(mapIn map[string]string) (map[string]string, error) { + mapOut := make(map[string]string) + for key, val := range mapIn { + mapOut[val] = key + } + return mapOut, nil +} + +// Returns mising keys in a map +func MissingMapKeys(inMap map[string]string, requiredKeys []string) []string { + missingKeys := []string{} + for _, reqKey := range requiredKeys { + if val, hasKey := inMap[reqKey]; !hasKey { + missingKeys = append(missingKeys, reqKey) + } else if val == "" { + missingKeys = append(missingKeys, reqKey) + } + } + return missingKeys +} + +// Return map keys +func MapKeys(m map[string]string) []string { + n := make([]string, len(m)) + i := 0 + for k := range m { + n[i] = k + i++ + } + return n +} diff --git a/utils/slice.go b/utils/slice.go new file mode 100644 index 000000000..7bc6c017e --- /dev/null +++ b/utils/slice.go @@ -0,0 +1,44 @@ +/* +Rating system designed to be used in VoIP Carriers World +Copyright (C) 2013 ITsysCOM + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see +*/ + + +package utils + +import ( + "sort" + "strings" +) + +// Binary string search in slice +func IsSliceMember(ss []string, s string) bool { + sort.Strings(ss) + if i := sort.SearchStrings(ss, s); i < len(ss) && ss[i] == s { + return true + } + return false +} + +//Iterates over slice members and returns true of one starts with prefix +func SliceMemberHasPrefix(ss []string, prfx string) bool { + for _, mbr := range ss { + if strings.HasPrefix(mbr, prfx) { + return true + } + } + return false +} diff --git a/utils/struct.go b/utils/struct.go new file mode 100644 index 000000000..172115f74 --- /dev/null +++ b/utils/struct.go @@ -0,0 +1,108 @@ +/* +Rating system designed to be used in VoIP Carriers World +Copyright (C) 2013 ITsysCOM + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see +*/ +package utils + +import ( + "reflect" + "strconv" +) + +// Detects missing field values based on mandatory field names, s should be a pointer to a struct +func MissingStructFields(s interface{}, mandatories []string) []string { + missing := []string{} + for _, fieldName := range mandatories { + fld := reflect.ValueOf(s).Elem().FieldByName(fieldName) + if (fld.Kind() == reflect.String && fld.String() == "") || + ((fld.Kind() == reflect.Slice || fld.Kind() == reflect.Map) && fld.Len() == 0) || + (fld.Kind() == reflect.Int && fld.Int() == 0) { + missing = append(missing, fieldName) + } + } + return missing +} + +// Detects nonempty struct fields, s should be a pointer to a struct +// Useful to not overwrite db fields with non defined params in api +func NonemptyStructFields(s interface{}) map[string]interface{} { + fields := make(map[string]interface{}) + for i := 0; i < reflect.ValueOf(s).Elem().NumField(); i++ { + fld := reflect.ValueOf(s).Elem().Field(i) + switch fld.Kind() { + case reflect.Bool: + fields[reflect.TypeOf(s).Elem().Field(i).Name] = fld.Bool() + case reflect.Int: + fieldVal := fld.Int() + if fieldVal != 0 { + fields[reflect.TypeOf(s).Elem().Field(i).Name] = fieldVal + } + case reflect.String: + fieldVal := fld.String() + if fieldVal != "" { + fields[reflect.TypeOf(s).Elem().Field(i).Name] = fieldVal + } + } + } + return fields +} + +// Converts a struct to map +func StrucToMap(s interface{}) map[string]interface{} { + mp := make(map[string]interface{}) + for i := 0; i < reflect.ValueOf(s).Elem().NumField(); i++ { + fld := reflect.ValueOf(s).Elem().Field(i) + switch fld.Kind() { + case reflect.Bool: + mp[reflect.TypeOf(s).Elem().Field(i).Name] = fld.Bool() + case reflect.Int: + mp[reflect.TypeOf(s).Elem().Field(i).Name] = fld.Int() + case reflect.String: + mp[reflect.TypeOf(s).Elem().Field(i).Name] = fld.String() + } + } + return mp +} + +// Update struct with map fields, returns not matching map keys, s is a struct to be updated +func UpdateStructWithStrMap(s interface{}, m map[string]string) []string { + notMatched := []string{} + for key, val := range m { + fld := reflect.ValueOf(s).Elem().FieldByName(key) + if fld.IsValid() { + switch fld.Kind() { + case reflect.Bool: + if valBool, err := strconv.ParseBool(val); err != nil { + notMatched = append(notMatched, key) + } else { + fld.SetBool(valBool) + } + case reflect.Int: + if valInt, err := strconv.ParseInt(val, 10, 64); err != nil { + notMatched = append(notMatched, key) + } else { + fld.SetInt(valInt) + } + case reflect.String: + fld.SetString(val) + } + } else { + notMatched = append(notMatched, key) + } + } + return notMatched +} +