Imported Upstream version 5.1.4

changes/09/21409/21 upstream/5.1.4
Marco Capetta 8 years ago
parent 13dca21bb6
commit 2e7b6d1012

File diff suppressed because it is too large Load Diff

@ -750,6 +750,14 @@ route[AUTH] {
exit;
}
#!else
# authentication not enabled - do not relay at all to foreign networks
if(uri!=myself) {
sl_send_reply("403","Not relaying");
exit;
}
#!endif
return;
}

@ -102,8 +102,6 @@ loadmodule "corex"
# Control interfaces:
loadmodule "ctl"
loadmodule "cfg_rpc"
loadmodule "mi_rpc"
loadmodule "mi_fifo"
#!ifdef WITH_XMLRPC
loadmodule "xmlrpc"
#!endif
@ -144,11 +142,13 @@ modparam("db_cluster", "connection", DB_URL2)
modparam("db_cluster", "cluster", "cluster1=>con1=2s2s;con2=1s1s")
#!endif
# ----- mi_fifo params -----
modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo")
modparam("mi_fifo", "fifo_mode", 0666)
modparam("mi_fifo", "fifo_user", "kamailio")
modparam("mi_fifo", "fifo_group", "kamailio")
loadmodule "jsonrpcs.so"
# ----- jsonrpcs params -----
modparam("jsonrpcs", "pretty_format", 1)
/* set the path to RPC fifo control file */
# modparam("jsonrpcs", "fifo_name", "/var/run/kamailio/kamailio_rpc.fifo")
/* set the path to RPC unix socket control file */
# modparam("jsonrpcs", "dgram_socket", "/var/run/kamailio/kamailio_rpc.sock")
# -- rr params --
# add value to ;lr param to make some broken UAs happy

@ -152,9 +152,7 @@ loadmodule "textopsx"
loadmodule "siputils"
loadmodule "sanity"
loadmodule "ctl"
loadmodule "mi_rpc"
loadmodule "cfg_rpc"
loadmodule "mi_fifo"
loadmodule "xlog"
loadmodule "auth"
loadmodule "dispatcher"
@ -237,11 +235,13 @@ modparam("debugger", "mod_level", "rtpengine=3")
modparam("debugger", "cfgtrace", 1)
#!endif
# ----- mi_fifo params -----
modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo")
modparam("mi_fifo", "fifo_mode", 0666)
modparam("mi_fifo", "fifo_user", "kamailio")
modparam("mi_fifo", "fifo_group", "kamailio")
loadmodule "jsonrpcs.so"
# ----- jsonrpcs params -----
modparam("jsonrpcs", "pretty_format", 1)
/* set the path to RPC fifo control file */
# modparam("jsonrpcs", "fifo_name", "/var/run/kamailio/kamailio_rpc.fifo")
/* set the path to RPC unix socket control file */
# modparam("jsonrpcs", "dgram_socket", "/var/run/kamailio/kamailio_rpc.sock")
# ----------------- setting module-specific parameters ---------------
#!ifdef DB_URL2
@ -905,5 +905,3 @@ include_file "route/register.cfg"
include_file "route/rtp.cfg"
include_file "route/mo.cfg"
include_file "route/mt.cfg"

@ -1,301 +1,301 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:simpleType name="tPriority" final="list restriction">
<xs:restriction base="xs:int">
<xs:minInclusive value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tProfilePartIndicator" final="list restriction">
<xs:restriction base="xs:unsignedByte">
<xs:maxInclusive value="1"/>
<xs:enumeration value="0">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">REGISTERED</label>
<definition xml:lang="en">iFC is part of the registered profile</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="1">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">UNREGISTERED</label>
<definition xml:lang="en">iFC is part of the unregistered profile</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tSharedIFCSetID" final="list restriction">
<xs:restriction base="xs:int">
<xs:minInclusive value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tGroupID" final="list restriction">
<xs:restriction base="xs:int">
<xs:minInclusive value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tRegistrationType" final="list restriction">
<xs:restriction base="xs:unsignedByte">
<xs:maxInclusive value="2"/>
<xs:enumeration value="0">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">INITIAL_REGISTRATION</label>
<definition xml:lang="en">Matches to REGISTER messages that are related to initial registration</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="1">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">RE-REGISTRATION</label>
<definition xml:lang="en">Matches to REGISTER messages that are related to re-registration</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="2">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">DE-REGISTRATION</label>
<definition xml:lang="en">Matches to REGISTER messages that are related to de-registration</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tDefaultHandling" final="list restriction">
<xs:restriction base="xs:unsignedByte">
<xs:maxInclusive value="1"/>
<xs:enumeration value="0">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">SESSION_CONTINUED</label>
<definition xml:lang="en">Session Continued</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="1">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">SESSION_TERMINATED</label>
<definition xml:lang="en">Session Terminated</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tDirectionOfRequest" final="list restriction">
<xs:restriction base="xs:unsignedByte">
<xs:maxInclusive value="3"/>
<xs:enumeration value="0">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">ORIGINATING_SESSION</label>
<definition xml:lang="en">Originating Session</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="1">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">TERMINATING_REGISTERED</label>
<definition xml:lang="en">Terminating Session for registered user</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="2">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">TERMINATING_UNREGISTERED</label>
<definition xml:lang="en">Terminating Session for unregistered user</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="3">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">ORIGINATING_UNREGISTERED</label>
<definition xml:lang="en">Originating Session for an unregistered user</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tPrivateID" final="list restriction">
<xs:restriction base="xs:anyURI"/>
</xs:simpleType>
<xs:simpleType name="tSIP_URL" final="list restriction">
<xs:restriction base="xs:anyURI"/>
</xs:simpleType>
<xs:simpleType name="tTEL_URL" final="list restriction">
<xs:restriction base="xs:anyURI"/>
</xs:simpleType>
<xs:simpleType name="tIdentity" final="list restriction">
<xs:union memberTypes="tSIP_URL tTEL_URL"/>
</xs:simpleType>
<xs:simpleType name="tIdentityType" final="list restriction">
<xs:restriction base="xs:unsignedByte">
<xs:minInclusive value="0"/>
<xs:maxInclusive value="2"/>
<xs:enumeration value="0">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">PUBLIC_USER_IDENTITY</label>
<definition xml:lang="en">Identity is a Public User Identity.</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="1">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">DISTINCT_PSI</label>
<definition xml:lang="en">Identity is a distinct Public Service Identity.</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="2">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">WILDCARDED_PSI</label>
<definition xml:lang="en">Identity matches a wildcarded Public Service Identity.</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="tPublicIdentityExtension">
<xs:sequence>
<xs:element name="IdentityType" type="tIdentityType" minOccurs="0"/>
<xs:element name="WildcardedPSI" type="xs:anyURI" minOccurs="0"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:simpleType name="tServiceInfo" final="list restriction">
<xs:restriction base="xs:string">
<xs:minLength value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tString" final="list restriction">
<xs:restriction base="xs:string">
<xs:minLength value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tBool">
<xs:restriction base="xs:boolean"/>
</xs:simpleType>
<xs:simpleType name="tSubscribedMediaProfileId" final="list restriction">
<xs:restriction base="xs:int">
<xs:minInclusive value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="tExtension">
<xs:sequence>
<xs:any processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tServiceProfileExtension">
<xs:sequence>
<xs:element name="SharedIFCSetID" type="tSharedIFCSetID" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tSePoTriExtension">
<xs:sequence>
<xs:element name="RegistrationType" type="tRegistrationType" minOccurs="0" maxOccurs="2"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tIMSSubscription">
<xs:sequence>
<xs:element name="PrivateID" type="tPrivateID"/>
<xs:element name="ServiceProfile" type="tServiceProfile" maxOccurs="unbounded"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tServiceProfile">
<xs:sequence>
<xs:element name="PublicIdentity" type="tPublicIdentity" maxOccurs="unbounded"/>
<xs:element name="CoreNetworkServicesAuthorization" type="tCoreNetworkServicesAuthorization" minOccurs="0"/>
<xs:element name="InitialFilterCriteria" type="tInitialFilterCriteria" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="Extension" type="tServiceProfileExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tCoreNetworkServicesAuthorization">
<xs:sequence>
<xs:element name="SubscribedMediaProfileId" type="tSubscribedMediaProfileId" minOccurs="0"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tInitialFilterCriteria">
<xs:sequence>
<xs:element name="Priority" type="tPriority"/>
<xs:element name="TriggerPoint" type="tTrigger" minOccurs="0"/>
<xs:element name="ApplicationServer" type="tApplicationServer"/>
<xs:element name="ProfilePartIndicator" type="tProfilePartIndicator" minOccurs="0"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tTrigger">
<xs:sequence>
<xs:element name="ConditionTypeCNF" type="tBool"/>
<xs:element name="SPT" type="tSePoTri" maxOccurs="unbounded"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tSePoTri">
<xs:sequence>
<xs:element name="ConditionNegated" type="tBool" default="0" minOccurs="0"/>
<xs:element name="Group" type="tGroupID" maxOccurs="unbounded"/>
<xs:choice>
<xs:element name="RequestURI" type="tString"/>
<xs:element name="Method" type="tString"/>
<xs:element name="SIPHeader" type="tHeader"/>
<xs:element name="SessionCase" type="tDirectionOfRequest"/>
<xs:element name="SessionDescription" type="tSessionDescription"/>
</xs:choice>
<xs:element name="Extension" type="tSePoTriExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tHeader">
<xs:sequence>
<xs:element name="Header" type="tString"/>
<xs:element name="Content" type="tString" minOccurs="0"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tSessionDescription">
<xs:sequence>
<xs:element name="Line" type="tString"/>
<xs:element name="Content" type="tString" minOccurs="0"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tApplicationServer">
<xs:sequence>
<xs:element name="ServerName" type="tSIP_URL"/>
<xs:element name="DefaultHandling" type="tDefaultHandling" minOccurs="0"/>
<xs:element name="ServiceInfo" type="tServiceInfo" minOccurs="0"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tPublicIdentity">
<xs:sequence>
<xs:element name="BarringIndication" type="tBool" default="0" minOccurs="0"/>
<xs:element name="Identity" type="tIdentity"/>
<xs:element name="Extension" type="tPublicIdentityExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:element name="IMSSubscription" type="tIMSSubscription"/>
</xs:schema>
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:simpleType name="tPriority" final="list restriction">
<xs:restriction base="xs:int">
<xs:minInclusive value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tProfilePartIndicator" final="list restriction">
<xs:restriction base="xs:unsignedByte">
<xs:maxInclusive value="1"/>
<xs:enumeration value="0">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">REGISTERED</label>
<definition xml:lang="en">iFC is part of the registered profile</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="1">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">UNREGISTERED</label>
<definition xml:lang="en">iFC is part of the unregistered profile</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tSharedIFCSetID" final="list restriction">
<xs:restriction base="xs:int">
<xs:minInclusive value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tGroupID" final="list restriction">
<xs:restriction base="xs:int">
<xs:minInclusive value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tRegistrationType" final="list restriction">
<xs:restriction base="xs:unsignedByte">
<xs:maxInclusive value="2"/>
<xs:enumeration value="0">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">INITIAL_REGISTRATION</label>
<definition xml:lang="en">Matches to REGISTER messages that are related to initial registration</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="1">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">RE-REGISTRATION</label>
<definition xml:lang="en">Matches to REGISTER messages that are related to re-registration</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="2">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">DE-REGISTRATION</label>
<definition xml:lang="en">Matches to REGISTER messages that are related to de-registration</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tDefaultHandling" final="list restriction">
<xs:restriction base="xs:unsignedByte">
<xs:maxInclusive value="1"/>
<xs:enumeration value="0">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">SESSION_CONTINUED</label>
<definition xml:lang="en">Session Continued</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="1">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">SESSION_TERMINATED</label>
<definition xml:lang="en">Session Terminated</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tDirectionOfRequest" final="list restriction">
<xs:restriction base="xs:unsignedByte">
<xs:maxInclusive value="3"/>
<xs:enumeration value="0">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">ORIGINATING_SESSION</label>
<definition xml:lang="en">Originating Session</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="1">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">TERMINATING_REGISTERED</label>
<definition xml:lang="en">Terminating Session for registered user</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="2">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">TERMINATING_UNREGISTERED</label>
<definition xml:lang="en">Terminating Session for unregistered user</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="3">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">ORIGINATING_UNREGISTERED</label>
<definition xml:lang="en">Originating Session for an unregistered user</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tPrivateID" final="list restriction">
<xs:restriction base="xs:anyURI"/>
</xs:simpleType>
<xs:simpleType name="tSIP_URL" final="list restriction">
<xs:restriction base="xs:anyURI"/>
</xs:simpleType>
<xs:simpleType name="tTEL_URL" final="list restriction">
<xs:restriction base="xs:anyURI"/>
</xs:simpleType>
<xs:simpleType name="tIdentity" final="list restriction">
<xs:union memberTypes="tSIP_URL tTEL_URL"/>
</xs:simpleType>
<xs:simpleType name="tIdentityType" final="list restriction">
<xs:restriction base="xs:unsignedByte">
<xs:minInclusive value="0"/>
<xs:maxInclusive value="2"/>
<xs:enumeration value="0">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">PUBLIC_USER_IDENTITY</label>
<definition xml:lang="en">Identity is a Public User Identity.</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="1">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">DISTINCT_PSI</label>
<definition xml:lang="en">Identity is a distinct Public Service Identity.</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="2">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">WILDCARDED_PSI</label>
<definition xml:lang="en">Identity matches a wildcarded Public Service Identity.</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="tPublicIdentityExtension">
<xs:sequence>
<xs:element name="IdentityType" type="tIdentityType" minOccurs="0"/>
<xs:element name="WildcardedPSI" type="xs:anyURI" minOccurs="0"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:simpleType name="tServiceInfo" final="list restriction">
<xs:restriction base="xs:string">
<xs:minLength value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tString" final="list restriction">
<xs:restriction base="xs:string">
<xs:minLength value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tBool">
<xs:restriction base="xs:boolean"/>
</xs:simpleType>
<xs:simpleType name="tSubscribedMediaProfileId" final="list restriction">
<xs:restriction base="xs:int">
<xs:minInclusive value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="tExtension">
<xs:sequence>
<xs:any processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tServiceProfileExtension">
<xs:sequence>
<xs:element name="SharedIFCSetID" type="tSharedIFCSetID" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tSePoTriExtension">
<xs:sequence>
<xs:element name="RegistrationType" type="tRegistrationType" minOccurs="0" maxOccurs="2"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tIMSSubscription">
<xs:sequence>
<xs:element name="PrivateID" type="tPrivateID"/>
<xs:element name="ServiceProfile" type="tServiceProfile" maxOccurs="unbounded"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tServiceProfile">
<xs:sequence>
<xs:element name="PublicIdentity" type="tPublicIdentity" maxOccurs="unbounded"/>
<xs:element name="CoreNetworkServicesAuthorization" type="tCoreNetworkServicesAuthorization" minOccurs="0"/>
<xs:element name="InitialFilterCriteria" type="tInitialFilterCriteria" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="Extension" type="tServiceProfileExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tCoreNetworkServicesAuthorization">
<xs:sequence>
<xs:element name="SubscribedMediaProfileId" type="tSubscribedMediaProfileId" minOccurs="0"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tInitialFilterCriteria">
<xs:sequence>
<xs:element name="Priority" type="tPriority"/>
<xs:element name="TriggerPoint" type="tTrigger" minOccurs="0"/>
<xs:element name="ApplicationServer" type="tApplicationServer"/>
<xs:element name="ProfilePartIndicator" type="tProfilePartIndicator" minOccurs="0"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tTrigger">
<xs:sequence>
<xs:element name="ConditionTypeCNF" type="tBool"/>
<xs:element name="SPT" type="tSePoTri" maxOccurs="unbounded"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tSePoTri">
<xs:sequence>
<xs:element name="ConditionNegated" type="tBool" default="0" minOccurs="0"/>
<xs:element name="Group" type="tGroupID" maxOccurs="unbounded"/>
<xs:choice>
<xs:element name="RequestURI" type="tString"/>
<xs:element name="Method" type="tString"/>
<xs:element name="SIPHeader" type="tHeader"/>
<xs:element name="SessionCase" type="tDirectionOfRequest"/>
<xs:element name="SessionDescription" type="tSessionDescription"/>
</xs:choice>
<xs:element name="Extension" type="tSePoTriExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tHeader">
<xs:sequence>
<xs:element name="Header" type="tString"/>
<xs:element name="Content" type="tString" minOccurs="0"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tSessionDescription">
<xs:sequence>
<xs:element name="Line" type="tString"/>
<xs:element name="Content" type="tString" minOccurs="0"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tApplicationServer">
<xs:sequence>
<xs:element name="ServerName" type="tSIP_URL"/>
<xs:element name="DefaultHandling" type="tDefaultHandling" minOccurs="0"/>
<xs:element name="ServiceInfo" type="tServiceInfo" minOccurs="0"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tPublicIdentity">
<xs:sequence>
<xs:element name="BarringIndication" type="tBool" default="0" minOccurs="0"/>
<xs:element name="Identity" type="tIdentity"/>
<xs:element name="Extension" type="tPublicIdentityExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:element name="IMSSubscription" type="tIMSSubscription"/>
</xs:schema>

@ -135,8 +135,6 @@ loadmodule "uac"
# Control interfaces:
loadmodule "ctl"
loadmodule "cfg_rpc"
loadmodule "mi_rpc"
loadmodule "mi_fifo"
#!ifdef WITH_XMLRPC
loadmodule "xmlrpc"
#!endif
@ -188,17 +186,13 @@ modparam("presence", "db_url", DB_URL)
modparam("presence", "db_update_period", 20)
#!endif
# ----- mi_fifo params -----
modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo")
modparam("mi_fifo", "fifo_mode", 0666)
modparam("mi_fifo", "fifo_user", "kamailio")
modparam("mi_fifo", "fifo_group", "kamailio")
# ----- mi_fifo params -----
modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo")
modparam("mi_fifo", "fifo_mode", 0666)
modparam("mi_fifo", "fifo_user", "kamailio")
modparam("mi_fifo", "fifo_group", "kamailio")
loadmodule "jsonrpcs.so"
# ----- jsonrpcs params -----
modparam("jsonrpcs", "pretty_format", 1)
/* set the path to RPC fifo control file */
# modparam("jsonrpcs", "fifo_name", "/var/run/kamailio/kamailio_rpc.fifo")
/* set the path to RPC unix socket control file */
# modparam("jsonrpcs", "dgram_socket", "/var/run/kamailio/kamailio_rpc.sock")
# ----- ctl params -----
modparam("ctl", "binrpc", "unix:/var/run/kamailio_scscf/kamailio_ctl")
@ -1227,4 +1221,3 @@ failure_route[PSTN_failure] {
exit;
}
}

@ -325,7 +325,7 @@ end
function ksr_route_sipout()
if KSR.is_myself(KSR.pv.get("$ru")) then return 1; end
KSR.hdr.append_hf("P-Hint: outbound\r\n");
KSR.hdr.append("P-Hint: outbound\r\n");
ksr_route_relay();
KSR.x.exit();
end

@ -360,6 +360,7 @@ cfgengine "python"
#!else
#!ifdef WITH_CFGLUA
modparam("app_lua", "reload", 1)
modparam("app_lua", "load", "/usr/local/etc/kamailio/kamailio-basic-kemi-lua.lua")
cfgengine "lua"
#!else

@ -4,7 +4,7 @@
# Maintainer: Nathan Angelacos <nangel@alpinelinux.org>
pkgname=kamailio
pkgver=5.1.1
pkgver=5.1.4
pkgrel=0
# If building from a git snapshot, specify the gitcommit

@ -1,5 +1,5 @@
%define name kamailio
%define ver 5.1.2
%define ver 5.1.4
%define rel 0%{dist}

@ -1,5 +1,5 @@
%define name kamailio
%define ver 5.1.2
%define ver 5.1.4
%define rel dev6%{dist}
%bcond_with dnssec

@ -1,3 +1,15 @@
kamailio (5.1.4) unstable; urgency=medium
* version set to 5.1.4
-- Victor Seva <vseva@debian.org> Tue, 05 Jun 2018 11:15:39 +0200
kamailio (5.1.3) unstable; urgency=medium
* version set to 5.1.3
-- Victor Seva <vseva@debian.org> Tue, 24 Apr 2018 10:34:57 +0200
kamailio (5.1.2) unstable; urgency=medium
* version set to 5.1.2

@ -1,3 +1,15 @@
kamailio (5.1.4) unstable; urgency=medium
* version set to 5.1.4
-- Victor Seva <vseva@debian.org> Tue, 05 Jun 2018 11:15:39 +0200
kamailio (5.1.3) unstable; urgency=medium
* version set to 5.1.3
-- Victor Seva <vseva@debian.org> Tue, 24 Apr 2018 10:34:57 +0200
kamailio (5.1.2) unstable; urgency=medium
* version set to 5.1.2

@ -1,3 +1,15 @@
kamailio (5.1.4) unstable; urgency=medium
* version set to 5.1.4
-- Victor Seva <vseva@debian.org> Tue, 05 Jun 2018 11:15:39 +0200
kamailio (5.1.3) unstable; urgency=medium
* version set to 5.1.3
-- Victor Seva <vseva@debian.org> Tue, 24 Apr 2018 10:34:57 +0200
kamailio (5.1.2) unstable; urgency=medium
* version set to 5.1.2

@ -1,3 +1,15 @@
kamailio (5.1.4) unstable; urgency=medium
* version set to 5.1.4
-- Victor Seva <vseva@debian.org> Tue, 05 Jun 2018 11:15:39 +0200
kamailio (5.1.3) unstable; urgency=medium
* version set to 5.1.3
-- Victor Seva <vseva@debian.org> Tue, 24 Apr 2018 10:34:57 +0200
kamailio (5.1.2) unstable; urgency=medium
* version set to 5.1.2

@ -1,3 +1,15 @@
kamailio (5.1.4) unstable; urgency=medium
* version set to 5.1.4
-- Victor Seva <vseva@debian.org> Tue, 05 Jun 2018 11:15:39 +0200
kamailio (5.1.3) unstable; urgency=medium
* version set to 5.1.3
-- Victor Seva <vseva@debian.org> Tue, 24 Apr 2018 10:34:57 +0200
kamailio (5.1.2) unstable; urgency=medium
* version set to 5.1.2

@ -1,3 +1,15 @@
kamailio (5.1.4) unstable; urgency=medium
* version set to 5.1.4
-- Victor Seva <vseva@debian.org> Tue, 05 Jun 2018 11:15:39 +0200
kamailio (5.1.3) unstable; urgency=medium
* version set to 5.1.3
-- Victor Seva <vseva@debian.org> Tue, 24 Apr 2018 10:34:57 +0200
kamailio (5.1.2) unstable; urgency=medium
* version set to 5.1.2

@ -1,3 +1,15 @@
kamailio (5.1.4) unstable; urgency=medium
* version set to 5.1.4
-- Victor Seva <vseva@debian.org> Tue, 05 Jun 2018 11:15:39 +0200
kamailio (5.1.3) unstable; urgency=medium
* version set to 5.1.3
-- Victor Seva <vseva@debian.org> Tue, 24 Apr 2018 10:34:57 +0200
kamailio (5.1.2) unstable; urgency=medium
* version set to 5.1.2

@ -1,3 +1,15 @@
kamailio (5.1.4) unstable; urgency=medium
* version set to 5.1.4
-- Victor Seva <vseva@debian.org> Tue, 05 Jun 2018 11:15:39 +0200
kamailio (5.1.3) unstable; urgency=medium
* version set to 5.1.3
-- Victor Seva <vseva@debian.org> Tue, 24 Apr 2018 10:34:57 +0200
kamailio (5.1.2) unstable; urgency=medium
* version set to 5.1.2

@ -1,3 +1,15 @@
kamailio (5.1.4) unstable; urgency=medium
* version set to 5.1.4
-- Victor Seva <vseva@debian.org> Tue, 05 Jun 2018 11:15:39 +0200
kamailio (5.1.3) unstable; urgency=medium
* version set to 5.1.3
-- Victor Seva <vseva@debian.org> Tue, 24 Apr 2018 10:34:57 +0200
kamailio (5.1.2) unstable; urgency=medium
* version set to 5.1.2

@ -1,5 +1,5 @@
%define name kamailio
%define ver 5.1.2
%define ver 5.1.4
%define rel 0%{dist}

@ -1,5 +1,5 @@
%define name kamailio
%define ver 5.1.2
%define ver 5.1.4
%define rel 0%{dist}
%if 0%{?fedora} == 25
@ -1118,7 +1118,7 @@ rm -rf %{buildroot}
%if "%{?_unitdir}" == ""
/sbin/chkconfig --add kamailio
%else
%tmpfiles_create kamailio
%tmpfiles_create kamailio.conf
/usr/bin/systemctl -q enable kamailio.service
%endif

@ -1,5 +1,5 @@
%define name kamailio
%define ver 5.1.2
%define ver 5.1.4
%define rel 0
%define _sharedir %{_prefix}/share

@ -1,5 +1,5 @@
%define name kamailio
%define ver 5.1.2
%define ver 5.1.4
%define rel 0
%define _sharedir %{_prefix}/share

@ -1,5 +1,5 @@
%define name kamailio
%define ver 5.1.2
%define ver 5.1.4
%define rel 0
%define EXCLUDED_MODULES mysql jabber cpl-c avp_radius auth_radius group_radius uri_radius pa postgres osp tlsops unixodbc

@ -1,5 +1,5 @@
%define name kamailio
%define ver 5.1.2
%define ver 5.1.4
%define rel 0
%define _sharedir %{_prefix}/share

@ -1,5 +1,5 @@
%define name kamailio
%define ver 5.1.2
%define ver 5.1.4
%define rel 0
%define EXCLUDED_MODULES mysql jabber cpl-c auth_radius misc_radius peering postgress pa unixodbc osp tlsops

@ -1,43 +1,43 @@
<?xml version="1.0"?>
<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
<!-- This is a manifest file to start, stop or restart the server automatically at
the Solaris 10 bootup. Setup and usage:
cp kamailio-manifest.xml to /var/svc/manifest/network/kamailio.xml
chmod 444 kamailio.xml
svccg -v import kamailio.xml
and finally enable the server to be a SMF service:
svcadm enable kamailio -->
<service_bundle type='manifest' name='kamailio'>
<service name='network/kamailio' type='service' version='1'>
<create_default_instance enabled='false' />
<single_instance/>
<dependency name='multi-user' grouping='require_all' restart_on='none' type='service'>
<service_fmri value='svc:/milestone/multi-user' />
</dependency>
<dependency name='multi-user-server' grouping='require_all' restart_on='none' type='service'>
<service_fmri value='svc:/milestone/multi-user-server' />
</dependency>
<dependency name='cswmysql5' grouping='require_all' restart_on='none' type='service'>
<!-- adapt if you use another mysql version -->
<service_fmri value='svc:/network/cswmysql5:default' />
</dependency>
<exec_method type='method' name='start' exec='/sbin/kamctl start' timeout_seconds='30' />
<exec_method type='method' name='stop' exec='/sbin/kamctl stop' timeout_seconds='60' />
<exec_method type='method' name='restart' exec='/sbin/kamctl restart' timeout_seconds='-1' />
<stability value='Unstable' />
<template>
<common_name>
<loctext xml:lang='C'> Kamailio </loctext>
</common_name>
</template>
</service>
</service_bundle>
<?xml version="1.0"?>
<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
<!-- This is a manifest file to start, stop or restart the server automatically at
the Solaris 10 bootup. Setup and usage:
cp kamailio-manifest.xml to /var/svc/manifest/network/kamailio.xml
chmod 444 kamailio.xml
svccg -v import kamailio.xml
and finally enable the server to be a SMF service:
svcadm enable kamailio -->
<service_bundle type='manifest' name='kamailio'>
<service name='network/kamailio' type='service' version='1'>
<create_default_instance enabled='false' />
<single_instance/>
<dependency name='multi-user' grouping='require_all' restart_on='none' type='service'>
<service_fmri value='svc:/milestone/multi-user' />
</dependency>
<dependency name='multi-user-server' grouping='require_all' restart_on='none' type='service'>
<service_fmri value='svc:/milestone/multi-user-server' />
</dependency>
<dependency name='cswmysql5' grouping='require_all' restart_on='none' type='service'>
<!-- adapt if you use another mysql version -->
<service_fmri value='svc:/network/cswmysql5:default' />
</dependency>
<exec_method type='method' name='start' exec='/sbin/kamctl start' timeout_seconds='30' />
<exec_method type='method' name='stop' exec='/sbin/kamctl stop' timeout_seconds='60' />
<exec_method type='method' name='restart' exec='/sbin/kamctl restart' timeout_seconds='-1' />
<stability value='Unstable' />
<template>
<common_name>
<loctext xml:lang='C'> Kamailio </loctext>
</common_name>
</template>
</service>
</service_bundle>

@ -106,7 +106,7 @@ INSTALL_FLAVOUR=$(FLAVOUR)
# version number
VERSION = 5
PATCHLEVEL = 1
SUBLEVEL = 2
SUBLEVEL = 4
EXTRAVERSION =
# memory manager switcher

@ -446,7 +446,7 @@ VERBOSE_STARTUP "verbose_startup"
SERVER_ID "server_id"
MAX_RECURSIVE_LEVEL "max_recursive_level"
MAX_BRANCHES_PARAM "max_branches"|"max_branches"
MAX_BRANCHES_PARAM "max_branches"
LATENCY_CFG_LOG latency_cfg_log
LATENCY_LOG latency_log

@ -1044,7 +1044,7 @@ static rpc_export_t core_rpc_methods[] = {
{"dns.debug_all", dns_cache_debug_all, dns_cache_debug_all_doc,
0 },
{"dns.view", dns_cache_view, dns_cache_view_doc,
0 },
RET_ARRAY },
{"dns.lookup", dns_cache_rpc_lookup, dns_cache_rpc_lookup_doc,
0 },
{"dns.delete_all", dns_cache_delete_all, dns_cache_delete_all_doc,

@ -231,6 +231,8 @@ void crcitt_string_array( char *dst, str src[], int size )
ccitt = 0xFFFF;
str_len=CRC16_LEN;
for (i=0; i<size; i++ ) {
/* invalid str with positive length and null char pointer */
if( unlikely(src[i].s==NULL)) break;
c=src[i].s;
len=src[i].len;
while(len) {

@ -3796,7 +3796,7 @@ static int dns_get_type(str* s)
/** rpc-prints a dns cache entry.
*/
void dns_cache_print_entry(rpc_t* rpc, void* ctx, struct dns_hash_entry* e)
int dns_cache_print_entry(rpc_t* rpc, void* ctx, struct dns_hash_entry* e)
{
int expires;
struct dns_rr* rr;
@ -3804,103 +3804,174 @@ void dns_cache_print_entry(rpc_t* rpc, void* ctx, struct dns_hash_entry* e)
ticks_t now;
str s;
int i;
int n;
void *th;
void *rh;
void *sh;
void *ih;
void *ah;
/* add entry node */
if(rpc->add(ctx, "{", &th) < 0) {
rpc->fault(ctx, 500, "Internal error root reply");
return -1;
}
now=get_ticks_raw();
expires = (s_ticks_t)(e->expire-now)<0?-1: TICKS_TO_S(e->expire-now);
rpc->rpl_printf(ctx, "%sname: %s", SPACE_FORMAT, e->name);
rpc->rpl_printf(ctx, "%stype: %s", SPACE_FORMAT, print_type(e->type));
rpc->rpl_printf(ctx, "%ssize (bytes): %d", SPACE_FORMAT,
e->total_size);
rpc->rpl_printf(ctx, "%sreference counter: %d", SPACE_FORMAT,
e->refcnt.val);
if (e->ent_flags & DNS_FLAG_PERMANENT) {
rpc->rpl_printf(ctx, "%spermanent: yes", SPACE_FORMAT);
} else {
rpc->rpl_printf(ctx, "%spermanent: no", SPACE_FORMAT);
rpc->rpl_printf(ctx, "%sexpires in (s): %d", SPACE_FORMAT, expires);
if(rpc->struct_add(th, "ssddsdds",
"name", e->name,
"type", print_type(e->type),
"size_bytes", e->total_size,
"reference_counter", e->refcnt.val,
"permanent", (e->ent_flags & DNS_FLAG_PERMANENT) ? "yes" : "no",
"expires", (e->ent_flags & DNS_FLAG_PERMANENT)?0:expires, /* seconds */
"last_used", TICKS_TO_S(now-e->last_used), /* seconds */
"negative_entry", (e->ent_flags & DNS_FLAG_BAD_NAME) ? "yes" : "no")
<0) {
rpc->fault(ctx, 500, "Internal error building structure");
return -1;
}
rpc->rpl_printf(ctx, "%slast used (s): %d", SPACE_FORMAT,
TICKS_TO_S(now-e->last_used));
rpc->rpl_printf(ctx, "%snegative entry: %s", SPACE_FORMAT,
(e->ent_flags & DNS_FLAG_BAD_NAME) ? "yes" : "no");
n = 0;
for (rr=e->rr_lst; rr; rr=rr->next) {
if(n==0) {
if(rpc->struct_add(th, "[", "records", &rh)<0) {
rpc->fault(ctx, 500, "Internal error building records");
return -1;
}
}
if(rpc->array_add(rh, "{", &sh) < 0) {
rpc->fault(ctx, 500, "Internal error adding record");
return -1;
}
if(rpc->struct_add(sh, "d", "rr_idx", n)<0) {
rpc->fault(ctx, 500, "Internal error adding rr_idx");
return -1;
}
n++;
switch(e->type) {
case T_A:
case T_AAAA:
if (dns_rr2ip(e->type, rr, &ip)==0){
rpc->rpl_printf(ctx, "%srr ip: %s", SPACE_FORMAT,
ip_addr2a(&ip) );
if(rpc->struct_add(sh, "s", "rr_ip", ip_addr2a(&ip))<0) {
rpc->fault(ctx, 500, "Internal error adding rr_ip");
return -1;
}
}else{
rpc->rpl_printf(ctx, "%srr ip: <error: bad rr>",
SPACE_FORMAT);
if(rpc->struct_add(sh, "s", "rr_ip", "error-bad-rr")<0) {
rpc->fault(ctx, 500, "Internal error adding rr_ip");
return -1;
}
}
break;
case T_SRV:
rpc->rpl_printf(ctx, "%srr name: %s", SPACE_FORMAT,
((struct srv_rdata*)(rr->rdata))->name);
rpc->rpl_printf(ctx, "%srr port: %d", SPACE_FORMAT,
((struct srv_rdata*)(rr->rdata))->port);
rpc->rpl_printf(ctx, "%srr priority: %d", SPACE_FORMAT,
((struct srv_rdata*)(rr->rdata))->priority);
rpc->rpl_printf(ctx, "%srr weight: %d", SPACE_FORMAT,
((struct srv_rdata*)(rr->rdata))->weight);
if(rpc->struct_add(sh, "sddd",
"rr_name", ((struct srv_rdata*)(rr->rdata))->name,
"rr_port", ((struct srv_rdata*)(rr->rdata))->port,
"rr_priority", ((struct srv_rdata*)(rr->rdata))->priority,
"rr_weight", ((struct srv_rdata*)(rr->rdata))->weight)<0) {
rpc->fault(ctx, 500, "Internal error adding rr srv fields");
return -1;
}
break;
case T_NAPTR:
rpc->rpl_printf(ctx, "%srr order: %d", SPACE_FORMAT,
((struct naptr_rdata*)(rr->rdata))->order);
rpc->rpl_printf(ctx, "%srr preference: %d", SPACE_FORMAT,
((struct naptr_rdata*)(rr->rdata))->pref);
if(rpc->struct_add(sh, "ds",
"rr_order", ((struct naptr_rdata*)(rr->rdata))->order,
"rr_preference", ((struct naptr_rdata*)(rr->rdata))->pref)
<0) {
rpc->fault(ctx, 500, "Internal error adding naptr order");
return -1;
}
s.s = ((struct naptr_rdata*)(rr->rdata))->flags;
s.len = ((struct naptr_rdata*)(rr->rdata))->flags_len;
rpc->rpl_printf(ctx, "%srr flags: %.*s", SPACE_FORMAT,
s.len, s.s);
if(rpc->struct_add(sh, "S", "rr_flags", &s)<0) {
rpc->fault(ctx, 500, "Internal error adding naptre rr_flags");
return -1;
}
s.s=((struct naptr_rdata*)(rr->rdata))->services;
s.len=((struct naptr_rdata*)(rr->rdata))->services_len;
rpc->rpl_printf(ctx, "%srr service: %.*s", SPACE_FORMAT,
s.len, s.s);
if(rpc->struct_add(sh, "S", "rr_service", &s)<0) {
rpc->fault(ctx, 500, "Internal error adding naptre rr_service");
return -1;
}
s.s = ((struct naptr_rdata*)(rr->rdata))->regexp;
s.len = ((struct naptr_rdata*)(rr->rdata))->regexp_len;
rpc->rpl_printf(ctx, "%srr regexp: %.*s", SPACE_FORMAT,
s.len, s.s);
if(rpc->struct_add(sh, "S", "rr_regexp", &s)<0) {
rpc->fault(ctx, 500, "Internal error adding naptre rr_regexp");
return -1;
}
s.s = ((struct naptr_rdata*)(rr->rdata))->repl;
s.len = ((struct naptr_rdata*)(rr->rdata))->repl_len;
rpc->rpl_printf(ctx, "%srr replacement: %.*s",
SPACE_FORMAT, s.len, s.s);
if(rpc->struct_add(sh, "S", "rr_regexp", &s)<0) {
rpc->fault(ctx, 500, "Internal error adding naptre rr_replacement");
return -1;
}
break;
case T_CNAME:
rpc->rpl_printf(ctx, "%srr name: %s", SPACE_FORMAT,
((struct cname_rdata*)(rr->rdata))->name);
if(rpc->struct_add(sh, "s", "rr_name",
((struct cname_rdata*)(rr->rdata))->name)<0) {
rpc->fault(ctx, 500, "Internal error adding cname rr_name");
return -1;
}
break;
case T_TXT:
if(rpc->struct_add(sh, "[", "txt", &ih)<0) {
rpc->fault(ctx, 500, "Internal error txt record");
return -1;
}
for (i=0; i<((struct txt_rdata*)(rr->rdata))->cstr_no;
i++){
rpc->rpl_printf(ctx, "%stxt[%d]: %s", SPACE_FORMAT, i,
((struct txt_rdata*)(rr->rdata))->txt[i].cstr);
if(rpc->array_add(ih, "{", &ah) < 0) {
rpc->fault(ctx, 500, "Internal error adding txt record");
return -1;
}
if(rpc->struct_add(ah, "ds", "idx", i,
"rr_txt",
((struct txt_rdata*)(rr->rdata))->txt[i].cstr)<0) {
rpc->fault(ctx, 500, "Internal error adding rr_txt");
return -1;
}
}
break;
case T_EBL:
rpc->rpl_printf(ctx, "%srr position: %d", SPACE_FORMAT,
((struct ebl_rdata*)(rr->rdata))->position);
rpc->rpl_printf(ctx, "%srr separator: %s", SPACE_FORMAT,
((struct ebl_rdata*)(rr->rdata))->separator);
rpc->rpl_printf(ctx, "%srr apex: %s", SPACE_FORMAT,
((struct ebl_rdata*)(rr->rdata))->apex);
if(rpc->struct_add(sh, "dss",
"rr_position", ((struct ebl_rdata*)(rr->rdata))->position,
"rr_separator", ((struct ebl_rdata*)(rr->rdata))->separator,
"rr_apex", ((struct ebl_rdata*)(rr->rdata))->apex)<0) {
rpc->fault(ctx, 500, "Internal error adding ebl fields");
return -1;
}
break;
case T_PTR:
rpc->rpl_printf(ctx, "%srr name: %s", SPACE_FORMAT,
((struct ptr_rdata*)(rr->rdata))->ptrdname);
if(rpc->struct_add(sh, "s", "rr_name",
((struct ptr_rdata*)(rr->rdata))->ptrdname)<0) {
rpc->fault(ctx, 500, "Internal error adding ptr rr_name");
return -1;
}
break;
default:
rpc->rpl_printf(ctx, "%sresource record: unknown",
SPACE_FORMAT);
if(rpc->struct_add(sh, "s", "rr_type", "unknown" )<0) {
rpc->fault(ctx, 500, "Internal error adding rr unknown");
return -1;
}
}
if ((e->ent_flags & DNS_FLAG_PERMANENT) == 0) {
if(rpc->struct_add(sh, "sd", "rr_permanent", "no",
"rr_expires",
(s_ticks_t)(rr->expire-now)<0?-1 :
TICKS_TO_S(rr->expire-now))<0) {
rpc->fault(ctx, 500, "Internal error adding rr_expires");
return -1;
}
} else {
if(rpc->struct_add(sh, "sd", "rr_permanent", "yes",
"rr_expires", 0)<0) {
rpc->fault(ctx, 500, "Internal error adding rr_expires");
return -1;
}
}
if ((e->ent_flags & DNS_FLAG_PERMANENT) == 0)
rpc->rpl_printf(ctx, "%srr expires in (s): %d", SPACE_FORMAT,
(s_ticks_t)(rr->expire-now)<0?-1 :
TICKS_TO_S(rr->expire-now));
}
return 0;
}
@ -3925,9 +3996,10 @@ void dns_cache_view(rpc_t* rpc, void* ctx)
) {
continue;
}
rpc->rpl_printf(ctx, "{\n");
dns_cache_print_entry(rpc, ctx, e);
rpc->rpl_printf(ctx, "}");
if(dns_cache_print_entry(rpc, ctx, e)<0) {
LM_DBG("failed to print dns entry\n");
return;
}
}
}
UNLOCK_DNS_HASH();
@ -3958,24 +4030,44 @@ void dns_cache_flush(int del_permanent)
/* deletes all the non-permanent entries from the cache */
void dns_cache_delete_all(rpc_t* rpc, void* ctx)
{
void *th;
if (!cfg_get(core, core_cfg, use_dns_cache)){
rpc->fault(ctx, 500, "dns cache support disabled (see use_dns_cache)");
return;
}
dns_cache_flush(0);
rpc->rpl_printf(ctx, "OK");
if(rpc->add(ctx, "{", &th) < 0) {
rpc->fault(ctx, 500, "Internal error - root structure");
return;
}
if(rpc->struct_add(th, "s", "status", "ok") < 0) {
rpc->fault(ctx, 500, "Internal error - status");
return;
}
}
/* deletes all the entries from the cache,
* even the permanent ones */
void dns_cache_delete_all_force(rpc_t* rpc, void* ctx)
{
void *th;
if (!cfg_get(core, core_cfg, use_dns_cache)){
rpc->fault(ctx, 500, "dns cache support disabled (see use_dns_cache)");
return;
}
dns_cache_flush(1);
rpc->rpl_printf(ctx, "OK");
if(rpc->add(ctx, "{", &th) < 0) {
rpc->fault(ctx, 500, "Internal error - root structure");
return;
}
if(rpc->struct_add(th, "s", "status", "ok") < 0) {
rpc->fault(ctx, 500, "Internal error - status");
return;
}
}
/* clones an entry and extends its memory area to hold a new rr.
@ -4610,7 +4702,9 @@ void dns_cache_rpc_lookup(rpc_t* rpc, void* ctx)
rpc->fault(ctx, 400, "Not found");
return;
}
dns_cache_print_entry(rpc, ctx, e);
if(dns_cache_print_entry(rpc, ctx, e)<0) {
LM_DBG("failed to print the dns entry\n");
}
dns_hash_put(e);
}

@ -92,6 +92,36 @@ static int sr_kemi_core_info(sip_msg_t *msg, str *txt)
return 0;
}
/**
*
*/
static int sr_kemi_core_warn(sip_msg_t *msg, str *txt)
{
if(txt!=NULL && txt->s!=NULL)
LM_WARN("%.*s", txt->len, txt->s);
return 0;
}
/**
*
*/
static int sr_kemi_core_notice(sip_msg_t *msg, str *txt)
{
if(txt!=NULL && txt->s!=NULL)
LM_NOTICE("%.*s", txt->len, txt->s);
return 0;
}
/**
*
*/
static int sr_kemi_core_crit(sip_msg_t *msg, str *txt)
{
if(txt!=NULL && txt->s!=NULL)
LM_CRIT("%.*s", txt->len, txt->s);
return 0;
}
/**
*
*/
@ -715,6 +745,21 @@ static sr_kemi_t _sr_kemi_core[] = {
{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
},
{ str_init(""), str_init("warn"),
SR_KEMIP_NONE, sr_kemi_core_warn,
{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
},
{ str_init(""), str_init("notice"),
SR_KEMIP_NONE, sr_kemi_core_notice,
{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
},
{ str_init(""), str_init("crit"),
SR_KEMIP_NONE, sr_kemi_core_crit,
{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
},
{ str_init(""), str_init("log"),
SR_KEMIP_NONE, sr_kemi_core_log,
{ SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE,

@ -85,8 +85,22 @@ typedef int (*sr_kemi_fmssn_f)(sip_msg_t*, str*, str*, int);
typedef int (*sr_kemi_fmsss_f)(sip_msg_t*, str*, str*, str*);
/* sip_msg_t and four int|str params */
typedef int (*sr_kemi_fmssss_f)(sip_msg_t*, str*, str*, str*, str*);
typedef int (*sr_kemi_fmnnnn_f)(sip_msg_t*, int, int, int, int);
typedef int (*sr_kemi_fmnnns_f)(sip_msg_t*, int, int, int, str*);
typedef int (*sr_kemi_fmnnsn_f)(sip_msg_t*, int, int, str*, int);
typedef int (*sr_kemi_fmnnss_f)(sip_msg_t*, int, int, str*, str*);
typedef int (*sr_kemi_fmnsnn_f)(sip_msg_t*, int, str*, int, int);
typedef int (*sr_kemi_fmnsns_f)(sip_msg_t*, int, str*, int, str*);
typedef int (*sr_kemi_fmnssn_f)(sip_msg_t*, int, str*, str*, int);
typedef int (*sr_kemi_fmnsss_f)(sip_msg_t*, int, str*, str*, str*);
typedef int (*sr_kemi_fmsnnn_f)(sip_msg_t*, str*, int, int, int);
typedef int (*sr_kemi_fmsnns_f)(sip_msg_t*, str*, int, int, str*);
typedef int (*sr_kemi_fmsnsn_f)(sip_msg_t*, str*, int, str*, int);
typedef int (*sr_kemi_fmsnss_f)(sip_msg_t*, str*, int, str*, str*);
typedef int (*sr_kemi_fmssnn_f)(sip_msg_t*, str*, str*, int, int);
typedef int (*sr_kemi_fmssns_f)(sip_msg_t*, str*, str*, int, str*);
typedef int (*sr_kemi_fmsssn_f)(sip_msg_t*, str*, str*, str*, int);
typedef int (*sr_kemi_fmssss_f)(sip_msg_t*, str*, str*, str*, str*);
/* sip_msg_t and five int|str params */
typedef int (*sr_kemi_fmsssss_f)(sip_msg_t*, str*, str*, str*, str*, str*);

@ -112,15 +112,18 @@ inline static unsigned long big_hash_idx(unsigned long s)
#define END_CHECK_PATTERN2 0xabcdefed
static void qm_debug_frag(struct qm_block* qm, struct qm_frag* f,
const char* file, unsigned int line)
#define qm_debug_frag(qm, f, file, line) \
qm_debug_check_frag((qm), (f), (file), (line), __FILE__, __LINE__)
static void qm_debug_check_frag(struct qm_block* qm, struct qm_frag* f,
const char* file, unsigned int line,
const char* efile, unsigned int eline)
{
if (f->check!=ST_CHECK_PATTERN){
LM_CRIT("BUG: qm: fragm. %p (address %p) "
"beginning overwritten (%lx)! Memory allocator was called "
"from %s:%u. Fragment marked by %s:%lu.\n",
"from %s:%u. Fragment marked by %s:%lu. Exec from %s:%u.\n",
f, (char*)f+sizeof(struct qm_frag),
f->check, file, line, f->file, f->line);
f->check, file, line, f->file, f->line, efile, eline);
qm_status(qm);
abort();
};
@ -128,10 +131,10 @@ static void qm_debug_frag(struct qm_block* qm, struct qm_frag* f,
(FRAG_END(f)->check2!=END_CHECK_PATTERN2)){
LM_CRIT("BUG: qm: fragm. %p (address %p) "
"end overwritten (%lx, %lx)! Memory allocator was called "
"from %s:%u. Fragment marked by %s:%lu.\n",
"from %s:%u. Fragment marked by %s:%lu. Exec from %s:%u.\n",
f, (char*)f+sizeof(struct qm_frag),
FRAG_END(f)->check1, FRAG_END(f)->check2,
file, line, f->file, f->line);
file, line, f->file, f->line, efile, eline);
qm_status(qm);
abort();
}
@ -140,9 +143,10 @@ static void qm_debug_frag(struct qm_block* qm, struct qm_frag* f,
(PREV_FRAG_END(f)->check2!=END_CHECK_PATTERN2) ) ){
LM_CRIT("BUG: qm: prev. fragm. tail overwritten(%lx, %lx)[%p:%p]! "
"Memory allocator was called from %s:%u. Fragment marked by "
"%s:%lu.\n",
"%s:%lu. Exec from %s:%u.\n",
PREV_FRAG_END(f)->check1, PREV_FRAG_END(f)->check2, f,
(char*)f+sizeof(struct qm_frag), file, line, f->file, f->line);
(char*)f+sizeof(struct qm_frag), file, line, f->file, f->line,
efile, eline);
qm_status(qm);
abort();
}

@ -168,12 +168,17 @@ static int check_via_address(struct ip_addr* ip, str *name,
(name->s[name->len-1]==']')&&
(strncasecmp(name->s+1, s, len)==0))
)
)
) {
return 0;
else
}
else {
if (unlikely(name->s==NULL)) {
LM_CRIT("invalid Via host name\n");
return -1;
}
if (strncmp(name->s, s, name->len)==0)
return 0;
}
}else{
LM_CRIT("could not convert ip address\n");
return -1;
@ -2367,7 +2372,7 @@ char * build_res_buf_from_sip_req( unsigned int code, str *text ,str *new_tag,
case HDR_TO_T:
if (new_tag && new_tag->len) {
to_tag=get_to(msg)->tag_value;
if ( to_tag.len || to_tag.s )
if ( to_tag.len && to_tag.s )
len+=new_tag->len-to_tag.len;
else
len+=new_tag->len+TOTAG_TOKEN_LEN/*";tag="*/;
@ -2495,7 +2500,7 @@ char * build_res_buf_from_sip_req( unsigned int code, str *text ,str *new_tag,
break;
case HDR_TO_T:
if (new_tag && new_tag->len){
if (to_tag.s ) { /* replacement */
if (to_tag.len && to_tag.s) { /* replacement */
/* before to-tag */
append_str( p, hdr->name.s, to_tag.s-hdr->name.s);
/* to tag replacement */

@ -70,7 +70,9 @@ static inline int run_onsend(sip_msg_t* orig_msg, dest_info_t* dst,
return 1;
}
ret=1;
if (onsend_rt.rlist[DEFAULT_RT]){
// do if onsend_route{} or cfgengine exists
keng = sr_kemi_eng_get();
if (onsend_rt.rlist[DEFAULT_RT] || keng){
onsnd_info.to=&dst->to;
onsnd_info.send_sock=dst->send_sock;
onsnd_info.buf=buf;
@ -86,8 +88,7 @@ static inline int run_onsend(sip_msg_t* orig_msg, dest_info_t* dst,
orig_msg->fwd_send_flags=dst->send_flags; /* intial value */
init_run_actions_ctx(&ra_ctx);
keng = sr_kemi_eng_get();
if(unlikely(keng!=NULL)) {
if(keng) {
bctx = sr_kemi_act_ctx_get();
sr_kemi_act_ctx_set(&ra_ctx);
ret=keng->froute(orig_msg, ONSEND_ROUTE, NULL, NULL);

@ -594,7 +594,7 @@ reload:
exit(-1);
}
mod_if_ver = (unsigned *)dlsym(handle, "module_interface_ver");
if ( (error =(char*)dlerror())!=0 ){
if (mod_if_ver==NULL || (error =(char*)dlerror())!=0 ){
LM_ERR("no module interface version in module <%s>\n", path );
goto error1;
}
@ -619,6 +619,9 @@ reload:
}
exp = (union module_exports_u*)dlsym(handle, "exports");
if(exp==NULL) {
error =(char*)dlerror();
LM_DBG("attempt to lookup exports structure failed - dlerror: %s\n",
(error)?error:"none");
/* 'exports' structure not found, look up for '_modulename_exports' */
mdir = strrchr(mod_path, '/');
if (!mdir) {
@ -630,10 +633,11 @@ reload:
if(expref.len>3 && strcmp(expref.s+expref.len-3, ".so")==0)
expref.len -= 3;
snprintf(exbuf, 62, "_%.*s_exports", expref.len, expref.s);
exp = (union module_exports_u*)dlsym(handle, exbuf);
LM_DBG("looking up exports with name: %s\n", exbuf);
if ( (error =(char*)dlerror())!=0 ){
LM_ERR("%s\n", error);
exp = (union module_exports_u*)dlsym(handle, exbuf);
if(exp==NULL || (error =(char*)dlerror())!=0 ){
LM_ERR("failure for exports symbol: %s - dlerror: %s\n",
exbuf, (error)?error:"none");
goto error1;
}
}

@ -60,7 +60,7 @@
#include "db_query.h"
#include "db.h"
static unsigned int MAX_URL_LENGTH = 255; /*!< maximum length of a SQL URL */
static unsigned int MAX_URL_LENGTH = 1023; /*!< maximum length of a SQL URL */
int db_check_api(db_func_t* dbf, char *mname)

@ -197,11 +197,11 @@ Options:\n\
-M nr Size of private memory allocated, in Megabytes\n\
-w dir Change the working directory to \"dir\" (default: \"/\")\n\
-t dir Chroot to \"dir\"\n\
-u uid Change uid \n\
-g gid Change gid \n\
-u uid Change uid (user id)\n\
-g gid Change gid (group id)\n\
-P file Create a pid file\n\
-G file Create a pgid file\n\
-Y dir Runtime dir\n\
-Y dir Runtime dir path\n\
-O nr Script optimization level (debugging option)\n\
-a mode Auto aliases mode: enable with yes or on,\n\
disable with no or off\n\
@ -211,7 +211,7 @@ Options:\n\
-X name Specify internal manager for private memory (pkg)\n\
- if omitted, the one for shm is used\n"
#ifdef STATS
" -s file File to which statistics is dumped (disabled otherwise)\n"
" -s file File where to write internal statistics on SIGUSR1\n"
#endif
;

@ -155,11 +155,23 @@ int sr_kemi_jsdt_return_int(duk_context *J, sr_kemi_t *ket, int rc)
return app_jsdt_return_false(J);
}
/**
*
*/
static int jsdt_sr_return_none(duk_context *J, int rmode)
{
if(rmode) {
duk_push_lstring(J, "<<null>>", 8);
return 1;
} else {
return 0;
}
}
/**
*
*/
static int jsdt_sr_pv_get(duk_context *J)
static int jsdt_sr_pv_get_mode(duk_context *J, int rmode)
{
str pvn;
pv_spec_t *pvs;
@ -171,28 +183,32 @@ static int jsdt_sr_pv_get(duk_context *J)
pvn.s = (char*)duk_to_string(J, 0);
if(pvn.s==NULL || env_J->msg==NULL)
return 0;
return jsdt_sr_return_none(J, rmode);
pvn.len = strlen(pvn.s);
LM_DBG("pv get: %s\n", pvn.s);
pl = pv_locate_name(&pvn);
if(pl != pvn.len) {
LM_ERR("invalid pv [%s] (%d/%d)\n", pvn.s, pl, pvn.len);
return 0;
return jsdt_sr_return_none(J, rmode);
}
pvs = pv_cache_get(&pvn);
if(pvs==NULL) {
LM_ERR("cannot get pv spec for [%s]\n", pvn.s);
return 0;
return jsdt_sr_return_none(J, rmode);
}
memset(&val, 0, sizeof(pv_value_t));
if(pv_get_spec_value(env_J->msg, pvs, &val) != 0) {
LM_ERR("unable to get pv value for [%s]\n", pvn.s);
return 0;
return jsdt_sr_return_none(J, rmode);
}
if(val.flags&PV_VAL_NULL) {
duk_push_string(J, NULL);
return 1;
if(rmode) {
jsdt_sr_return_none(J, rmode);
} else {
duk_push_string(J, NULL);
return 1;
}
}
if(val.flags&PV_TYPE_INT) {
duk_push_int(J, val.ri);
@ -202,6 +218,22 @@ static int jsdt_sr_pv_get(duk_context *J)
return 1;
}
/**
*
*/
static int jsdt_sr_pv_get(duk_context *J)
{
return jsdt_sr_pv_get_mode(J, 0);
}
/**
*
*/
static int jsdt_sr_pv_getw(duk_context *J)
{
return jsdt_sr_pv_get_mode(J, 1);
}
/**
*
*/
@ -392,6 +424,7 @@ static int jsdt_sr_pv_is_null (duk_context *J)
const duk_function_list_entry _sr_kemi_pv_J_Map[] = {
{ "get", jsdt_sr_pv_get, 1 /* 1 args */ },
{ "getw", jsdt_sr_pv_getw, 1 /* 1 args */ },
{ "seti", jsdt_sr_pv_seti, 2 /* 2 args */ },
{ "sets", jsdt_sr_pv_sets, 2 /* 2 args */ },
{ "unset", jsdt_sr_pv_unset, 1 /* 1 args */ },
@ -1088,19 +1121,33 @@ int sr_kemi_jsdt_exec_func_ex(duk_context *J, sr_kemi_t *ket)
break;
case 4:
if(ket->ptypes[0]==SR_KEMIP_STR
|| ket->ptypes[1]==SR_KEMIP_STR
|| ket->ptypes[2]==SR_KEMIP_STR
|| ket->ptypes[3]==SR_KEMIP_STR) {
&& ket->ptypes[1]==SR_KEMIP_STR
&& ket->ptypes[2]==SR_KEMIP_STR
&& ket->ptypes[3]==SR_KEMIP_STR) {
ret = ((sr_kemi_fmssss_f)(ket->func))(env_J->msg,
&vps[0].s, &vps[1].s, &vps[2].s, &vps[3].s);
return sr_kemi_jsdt_return_int(J, ket, ret);
} else if(ket->ptypes[0]==SR_KEMIP_STR
|| ket->ptypes[1]==SR_KEMIP_STR
|| ket->ptypes[2]==SR_KEMIP_INT
|| ket->ptypes[3]==SR_KEMIP_INT) {
&& ket->ptypes[1]==SR_KEMIP_STR
&& ket->ptypes[2]==SR_KEMIP_STR
&& ket->ptypes[3]==SR_KEMIP_INT) {
ret = ((sr_kemi_fmsssn_f)(ket->func))(env_J->msg,
&vps[0].s, &vps[1].s, &vps[2].s, vps[3].n);
return sr_kemi_jsdt_return_int(J, ket, ret);
} else if(ket->ptypes[0]==SR_KEMIP_STR
&& ket->ptypes[1]==SR_KEMIP_STR
&& ket->ptypes[2]==SR_KEMIP_INT
&& ket->ptypes[3]==SR_KEMIP_INT) {
ret = ((sr_kemi_fmssnn_f)(ket->func))(env_J->msg,
&vps[0].s, &vps[1].s, vps[2].n, vps[3].n);
return sr_kemi_jsdt_return_int(J, ket, ret);
} else if(ket->ptypes[0]==SR_KEMIP_INT
&& ket->ptypes[1]==SR_KEMIP_STR
&& ket->ptypes[2]==SR_KEMIP_STR
&& ket->ptypes[3]==SR_KEMIP_STR) {
ret = ((sr_kemi_fmnsss_f)(ket->func))(env_J->msg,
vps[0].n, &vps[1].s, &vps[2].s, &vps[3].s);
return sr_kemi_jsdt_return_int(J, ket, ret);
} else {
LM_ERR("invalid parameters for: %.*s\n",
fname->len, fname->s);
@ -1109,10 +1156,10 @@ int sr_kemi_jsdt_exec_func_ex(duk_context *J, sr_kemi_t *ket)
break;
case 5:
if(ket->ptypes[0]==SR_KEMIP_STR
|| ket->ptypes[1]==SR_KEMIP_STR
|| ket->ptypes[2]==SR_KEMIP_STR
|| ket->ptypes[3]==SR_KEMIP_STR
|| ket->ptypes[4]==SR_KEMIP_STR) {
&& ket->ptypes[1]==SR_KEMIP_STR
&& ket->ptypes[2]==SR_KEMIP_STR
&& ket->ptypes[3]==SR_KEMIP_STR
&& ket->ptypes[4]==SR_KEMIP_STR) {
ret = ((sr_kemi_fmsssss_f)(ket->func))(env_J->msg,
&vps[0].s, &vps[1].s, &vps[2].s, &vps[3].s,
&vps[4].s);
@ -1125,11 +1172,11 @@ int sr_kemi_jsdt_exec_func_ex(duk_context *J, sr_kemi_t *ket)
break;
case 6:
if(ket->ptypes[0]==SR_KEMIP_STR
|| ket->ptypes[1]==SR_KEMIP_STR
|| ket->ptypes[2]==SR_KEMIP_STR
|| ket->ptypes[3]==SR_KEMIP_STR
|| ket->ptypes[4]==SR_KEMIP_STR
|| ket->ptypes[5]==SR_KEMIP_STR) {
&& ket->ptypes[1]==SR_KEMIP_STR
&& ket->ptypes[2]==SR_KEMIP_STR
&& ket->ptypes[3]==SR_KEMIP_STR
&& ket->ptypes[4]==SR_KEMIP_STR
&& ket->ptypes[5]==SR_KEMIP_STR) {
ret = ((sr_kemi_fmssssss_f)(ket->func))(env_J->msg,
&vps[0].s, &vps[1].s, &vps[2].s, &vps[3].s,
&vps[4].s, &vps[5].s);

@ -17,15 +17,16 @@
<section>
<title>Overview</title>
<para>
This module allows executing JavaScript scripts from config file.
This module allows executing JavaScript scripts from the Kamailio
configuration file.
It exports all KEMI functions to JavaScript in order to access the
current processed SIP message. These functions are within JavaScript
object 'KSR'.
currently processed SIP message. These functions are named within
the JavaScript object 'KSR'.
</para>
<para>
It includes the Duktape JavaScript engine (http://www.duktape.org),
which is a fast and easy to embed JavaScript interpreter. Exported API
from SIP router to JavaScript is documented in the dokuwiki.
The module is based on the Duktape JavaScript engine (http://www.duktape.org),
which is a fast and easy to embed JavaScript interpreter. The exported API
from Kamailio to JavaScript is documented in the wiki.
</para>
<para>
The module has two JavaScript contexts:
@ -116,7 +117,7 @@ modparam("app_jsdt", "load", "/usr/local/etc/kamailio/js/myscript.js")
<function moreinfo="none">jsdt_dofile(path)</function>
</title>
<para>
Execute the JS script stored in 'path'. The parameter can be
Execute the JavaScript script stored in 'path'. The parameter can be
a string with pseudo-variables evaluated at runtime.
</para>
<example>
@ -134,7 +135,7 @@ jsdt_dofile("/usr/local/etc/kamailio/js/myscript.js");
<function moreinfo="none">jsdt_dostring(script)</function>
</title>
<para>
Execute the Lua script stored in parameter. The parameter can be
Execute the JavaScript script stored in parameter. The parameter can be
a string with pseudo-variables.
</para>
<example>
@ -248,7 +249,7 @@ if(!jsdt_runstring('KSR.dbg("Hello World from $fU\n")'))
<section>
<title>Example of usage</title>
<para>
Create your JS script and stored on file system,
Create your JS script and store it on the file system,
say: '/usr/local/etc/kamailio/js/myscript.js'.
</para>
<programlisting format="linespecific">

@ -884,7 +884,7 @@ static const luaL_Reg _sr_hdr_Map [] = {
/**
*
*/
static int lua_sr_pv_get (lua_State *L)
static int lua_sr_pv_get_val (lua_State *L, int rmode)
{
str pvn;
pv_spec_t *pvs;
@ -895,35 +895,56 @@ static int lua_sr_pv_get (lua_State *L)
env_L = sr_lua_env_get();
pvn.s = (char*)lua_tostring(L, -1);
if(pvn.s==NULL || env_L->msg==NULL)
return 0;
if(pvn.s==NULL || env_L->msg==NULL) {
if(rmode) {
lua_pushlstring(L, "<<null>>", 8);
return 1;
} else {
return 0;
}
}
pvn.len = strlen(pvn.s);
LM_DBG("pv get: %s\n", pvn.s);
pl = pv_locate_name(&pvn);
if(pl != pvn.len)
{
if(pl != pvn.len) {
LM_ERR("invalid pv [%s] (%d/%d)\n", pvn.s, pl, pvn.len);
return 0;
if(rmode) {
lua_pushlstring(L, "<<null>>", 8);
return 1;
} else {
return 0;
}
}
pvs = pv_cache_get(&pvn);
if(pvs==NULL)
{
if(pvs==NULL) {
LM_ERR("cannot get pv spec for [%s]\n", pvn.s);
return 0;
if(rmode) {
lua_pushlstring(L, "<<null>>", 8);
return 1;
} else {
return 0;
}
}
memset(&val, 0, sizeof(pv_value_t));
if(pv_get_spec_value(env_L->msg, pvs, &val) != 0)
{
if(pv_get_spec_value(env_L->msg, pvs, &val) != 0) {
LM_ERR("unable to get pv value for [%s]\n", pvn.s);
return 0;
if(rmode) {
lua_pushlstring(L, "<<null>>", 8);
return 1;
} else {
return 0;
}
}
if(val.flags&PV_VAL_NULL)
{
return 0;
if(val.flags&PV_VAL_NULL) {
if(rmode) {
lua_pushlstring(L, "<<null>>", 8);
return 1;
} else {
return 0;
}
}
if(val.flags&PV_TYPE_INT)
{
if(val.flags&PV_TYPE_INT) {
lua_pushinteger(L, val.ri);
return 1;
}
@ -931,6 +952,22 @@ static int lua_sr_pv_get (lua_State *L)
return 1;
}
/**
*
*/
static int lua_sr_pv_get (lua_State *L)
{
return lua_sr_pv_get_val(L, 0);
}
/**
*
*/
static int lua_sr_pv_getw (lua_State *L)
{
return lua_sr_pv_get_val(L, 1);
}
/**
*
*/
@ -1137,6 +1174,7 @@ static int lua_sr_pv_is_null (lua_State *L)
*/
static const luaL_Reg _sr_pv_Map [] = {
{"get", lua_sr_pv_get},
{"getw", lua_sr_pv_getw},
{"seti", lua_sr_pv_seti},
{"sets", lua_sr_pv_sets},
{"unset", lua_sr_pv_unset},
@ -1489,9 +1527,27 @@ int sr_kemi_lua_exec_func_ex(lua_State* L, sr_kemi_t *ket, int pdelta)
for(i=0; i<SR_KEMI_PARAMS_MAX; i++) {
if(ket->ptypes[i]==SR_KEMIP_NONE) {
break;
} else if(ket->ptypes[i]==SR_KEMIP_STR) {
}
if(argc<i+pdelta+1) {
LM_ERR("not enough parameters for: %.*s.%.*s\n",
mname->len, mname->s, fname->len, fname->s);
return app_lua_return_false(L);
}
if(ket->ptypes[i]==SR_KEMIP_STR) {
vps[i].s.s = (char*)lua_tostring(L, i+pdelta+1);
vps[i].s.len = strlen(vps[i].s.s);
if(vps[i].s.s!=NULL) {
if(lua_isstring(L, i+pdelta+1)) {
#if LUA_VERSION_NUM > 501
vps[i].s.len = lua_rawlen(L, i+pdelta+1);
#else
vps[i].s.len = lua_strlen(L, i+pdelta+1);
#endif
} else {
vps[i].s.len = strlen(vps[i].s.s);
}
} else {
vps[i].s.len = 0;
}
LM_DBG("param[%d] for: %.*s is str: %.*s\n", i,
fname->len, fname->s, vps[i].s.len, vps[i].s.s);
} else if(ket->ptypes[i]==SR_KEMIP_INT) {
@ -1626,19 +1682,33 @@ int sr_kemi_lua_exec_func_ex(lua_State* L, sr_kemi_t *ket, int pdelta)
break;
case 4:
if(ket->ptypes[0]==SR_KEMIP_STR
|| ket->ptypes[1]==SR_KEMIP_STR
|| ket->ptypes[2]==SR_KEMIP_STR
|| ket->ptypes[3]==SR_KEMIP_STR) {
&& ket->ptypes[1]==SR_KEMIP_STR
&& ket->ptypes[2]==SR_KEMIP_STR
&& ket->ptypes[3]==SR_KEMIP_STR) {
ret = ((sr_kemi_fmssss_f)(ket->func))(env_L->msg,
&vps[0].s, &vps[1].s, &vps[2].s, &vps[3].s);
return sr_kemi_lua_return_int(L, ket, ret);
} else if(ket->ptypes[0]==SR_KEMIP_STR
|| ket->ptypes[1]==SR_KEMIP_STR
|| ket->ptypes[2]==SR_KEMIP_INT
|| ket->ptypes[3]==SR_KEMIP_INT) {
&& ket->ptypes[1]==SR_KEMIP_STR
&& ket->ptypes[2]==SR_KEMIP_STR
&& ket->ptypes[3]==SR_KEMIP_INT) {
ret = ((sr_kemi_fmsssn_f)(ket->func))(env_L->msg,
&vps[0].s, &vps[1].s, &vps[2].s, vps[3].n);
return sr_kemi_lua_return_int(L, ket, ret);
} else if(ket->ptypes[0]==SR_KEMIP_STR
&& ket->ptypes[1]==SR_KEMIP_STR
&& ket->ptypes[2]==SR_KEMIP_INT
&& ket->ptypes[3]==SR_KEMIP_INT) {
ret = ((sr_kemi_fmssnn_f)(ket->func))(env_L->msg,
&vps[0].s, &vps[1].s, vps[2].n, vps[3].n);
return sr_kemi_lua_return_int(L, ket, ret);
} else if(ket->ptypes[0]==SR_KEMIP_INT
&& ket->ptypes[1]==SR_KEMIP_STR
&& ket->ptypes[2]==SR_KEMIP_STR
&& ket->ptypes[3]==SR_KEMIP_STR) {
ret = ((sr_kemi_fmnsss_f)(ket->func))(env_L->msg,
vps[0].n, &vps[1].s, &vps[2].s, &vps[3].s);
return sr_kemi_lua_return_int(L, ket, ret);
} else {
LM_ERR("invalid parameters for: %.*s\n",
fname->len, fname->s);
@ -1647,10 +1717,10 @@ int sr_kemi_lua_exec_func_ex(lua_State* L, sr_kemi_t *ket, int pdelta)
break;
case 5:
if(ket->ptypes[0]==SR_KEMIP_STR
|| ket->ptypes[1]==SR_KEMIP_STR
|| ket->ptypes[2]==SR_KEMIP_STR
|| ket->ptypes[3]==SR_KEMIP_STR
|| ket->ptypes[4]==SR_KEMIP_STR) {
&& ket->ptypes[1]==SR_KEMIP_STR
&& ket->ptypes[2]==SR_KEMIP_STR
&& ket->ptypes[3]==SR_KEMIP_STR
&& ket->ptypes[4]==SR_KEMIP_STR) {
ret = ((sr_kemi_fmsssss_f)(ket->func))(env_L->msg,
&vps[0].s, &vps[1].s, &vps[2].s, &vps[3].s,
&vps[4].s);
@ -1663,11 +1733,11 @@ int sr_kemi_lua_exec_func_ex(lua_State* L, sr_kemi_t *ket, int pdelta)
break;
case 6:
if(ket->ptypes[0]==SR_KEMIP_STR
|| ket->ptypes[1]==SR_KEMIP_STR
|| ket->ptypes[2]==SR_KEMIP_STR
|| ket->ptypes[3]==SR_KEMIP_STR
|| ket->ptypes[4]==SR_KEMIP_STR
|| ket->ptypes[5]==SR_KEMIP_STR) {
&& ket->ptypes[1]==SR_KEMIP_STR
&& ket->ptypes[2]==SR_KEMIP_STR
&& ket->ptypes[3]==SR_KEMIP_STR
&& ket->ptypes[4]==SR_KEMIP_STR
&& ket->ptypes[5]==SR_KEMIP_STR) {
ret = ((sr_kemi_fmssssss_f)(ket->func))(env_L->msg,
&vps[0].s, &vps[1].s, &vps[2].s, &vps[3].s,
&vps[4].s, &vps[5].s);

@ -578,21 +578,37 @@ PyObject *sr_apy_kemi_exec_func(PyObject *self, PyObject *args, int idx)
break;
case 4:
if(ket->ptypes[0]==SR_KEMIP_STR
|| ket->ptypes[1]==SR_KEMIP_STR
|| ket->ptypes[2]==SR_KEMIP_STR
|| ket->ptypes[3]==SR_KEMIP_STR) {
&& ket->ptypes[1]==SR_KEMIP_STR
&& ket->ptypes[2]==SR_KEMIP_STR
&& ket->ptypes[3]==SR_KEMIP_STR) {
/* ssss */
ret = ((sr_kemi_fmssss_f)(ket->func))(lmsg,
&vps[0].s, &vps[1].s, &vps[2].s, &vps[3].s);
return sr_kemi_apy_return_int(ket, ret);
} else if(ket->ptypes[0]==SR_KEMIP_STR
|| ket->ptypes[1]==SR_KEMIP_STR
|| ket->ptypes[2]==SR_KEMIP_INT
|| ket->ptypes[3]==SR_KEMIP_INT) {
&& ket->ptypes[1]==SR_KEMIP_STR
&& ket->ptypes[2]==SR_KEMIP_STR
&& ket->ptypes[3]==SR_KEMIP_INT) {
/* ssnn */
ret = ((sr_kemi_fmsssn_f)(ket->func))(lmsg,
&vps[0].s, &vps[1].s, &vps[2].s, vps[3].n);
return sr_kemi_apy_return_int(ket, ret);
} else if(ket->ptypes[0]==SR_KEMIP_STR
&& ket->ptypes[1]==SR_KEMIP_STR
&& ket->ptypes[2]==SR_KEMIP_INT
&& ket->ptypes[3]==SR_KEMIP_INT) {
/* ssnn */
ret = ((sr_kemi_fmssnn_f)(ket->func))(lmsg,
&vps[0].s, &vps[1].s, vps[2].n, vps[3].n);
return sr_kemi_apy_return_int(ket, ret);
} else if(ket->ptypes[0]==SR_KEMIP_INT
&& ket->ptypes[1]==SR_KEMIP_STR
&& ket->ptypes[2]==SR_KEMIP_STR
&& ket->ptypes[3]==SR_KEMIP_STR) {
/* ssnn */
ret = ((sr_kemi_fmnsss_f)(ket->func))(lmsg,
vps[0].n, &vps[1].s, &vps[2].s, &vps[3].s);
return sr_kemi_apy_return_int(ket, ret);
} else {
LM_ERR("invalid parameters for: %.*s\n",
fname.len, fname.s);
@ -601,10 +617,10 @@ PyObject *sr_apy_kemi_exec_func(PyObject *self, PyObject *args, int idx)
break;
case 5:
if(ket->ptypes[0]==SR_KEMIP_STR
|| ket->ptypes[1]==SR_KEMIP_STR
|| ket->ptypes[2]==SR_KEMIP_STR
|| ket->ptypes[3]==SR_KEMIP_STR
|| ket->ptypes[4]==SR_KEMIP_STR) {
&& ket->ptypes[1]==SR_KEMIP_STR
&& ket->ptypes[2]==SR_KEMIP_STR
&& ket->ptypes[3]==SR_KEMIP_STR
&& ket->ptypes[4]==SR_KEMIP_STR) {
/* sssss */
ret = ((sr_kemi_fmsssss_f)(ket->func))(lmsg,
&vps[0].s, &vps[1].s, &vps[2].s, &vps[3].s,
@ -618,11 +634,11 @@ PyObject *sr_apy_kemi_exec_func(PyObject *self, PyObject *args, int idx)
break;
case 6:
if(ket->ptypes[0]==SR_KEMIP_STR
|| ket->ptypes[1]==SR_KEMIP_STR
|| ket->ptypes[2]==SR_KEMIP_STR
|| ket->ptypes[3]==SR_KEMIP_STR
|| ket->ptypes[4]==SR_KEMIP_STR
|| ket->ptypes[5]==SR_KEMIP_STR) {
&& ket->ptypes[1]==SR_KEMIP_STR
&& ket->ptypes[2]==SR_KEMIP_STR
&& ket->ptypes[3]==SR_KEMIP_STR
&& ket->ptypes[4]==SR_KEMIP_STR
&& ket->ptypes[5]==SR_KEMIP_STR) {
/* ssssss */
ret = ((sr_kemi_fmssssss_f)(ket->func))(lmsg,
&vps[0].s, &vps[1].s, &vps[2].s, &vps[3].s,
@ -678,7 +694,20 @@ static sr_kemi_t _sr_apy_kemi_test[] = {
/**
*
*/
static PyObject *sr_apy_kemi_f_pv_get(PyObject *self, PyObject *args)
PyObject *sr_apy_kemi_return_none_mode(int rmode)
{
if(rmode) {
return sr_apy_kemi_return_str(NULL, "<<null>>", 8);
} else {
return sr_apy_kemi_return_none();
}
}
/**
*
*/
static PyObject *sr_apy_kemi_f_pv_get_mode(PyObject *self, PyObject *args,
int rmode)
{
str pvn;
pv_spec_t *pvs;
@ -691,7 +720,7 @@ static PyObject *sr_apy_kemi_f_pv_get(PyObject *self, PyObject *args)
if(env_P==NULL) {
LM_ERR("invalid Python environment attributes\n");
return sr_apy_kemi_return_none();
return sr_apy_kemi_return_none_mode(rmode);
}
if(env_P->msg==NULL) {
lmsg = faked_msg_next();
@ -701,12 +730,12 @@ static PyObject *sr_apy_kemi_f_pv_get(PyObject *self, PyObject *args)
if(!PyArg_ParseTuple(args, "s:pv.get", &pvn.s)) {
LM_ERR("unable to retrieve str param\n");
return sr_apy_kemi_return_none();
return sr_apy_kemi_return_none_mode(rmode);
}
if(pvn.s==NULL || lmsg==NULL) {
LM_ERR("invalid context attributes\n");
return sr_apy_kemi_return_none();
return sr_apy_kemi_return_none_mode(rmode);
}
pvn.len = strlen(pvn.s);
@ -714,21 +743,21 @@ static PyObject *sr_apy_kemi_f_pv_get(PyObject *self, PyObject *args)
pl = pv_locate_name(&pvn);
if(pl != pvn.len) {
LM_ERR("invalid pv [%s] (%d/%d)\n", pvn.s, pl, pvn.len);
return sr_apy_kemi_return_none();
return sr_apy_kemi_return_none_mode(rmode);
}
pvs = pv_cache_get(&pvn);
if(pvs==NULL) {
LM_ERR("cannot get pv spec for [%s]\n", pvn.s);
return sr_apy_kemi_return_none();
return sr_apy_kemi_return_none_mode(rmode);
}
memset(&val, 0, sizeof(pv_value_t));
if(pv_get_spec_value(lmsg, pvs, &val) != 0)
{
LM_ERR("unable to get pv value for [%s]\n", pvn.s);
return sr_apy_kemi_return_none();
return sr_apy_kemi_return_none_mode(rmode);
}
if(val.flags&PV_VAL_NULL) {
return sr_apy_kemi_return_none();
return sr_apy_kemi_return_none_mode(rmode);
}
if(val.flags&PV_TYPE_INT) {
return sr_kemi_apy_return_int(NULL, val.ri);
@ -736,6 +765,22 @@ static PyObject *sr_apy_kemi_f_pv_get(PyObject *self, PyObject *args)
return sr_apy_kemi_return_str(NULL, val.rs.s, val.rs.len);
}
/**
*
*/
static PyObject *sr_apy_kemi_f_pv_get(PyObject *self, PyObject *args)
{
return sr_apy_kemi_f_pv_get_mode(self, args, 0);
}
/**
*
*/
static PyObject *sr_apy_kemi_f_pv_getw(PyObject *self, PyObject *args)
{
return sr_apy_kemi_f_pv_get_mode(self, args, 1);
}
/**
*
*/
@ -967,6 +1012,8 @@ static PyObject *sr_apy_kemi_f_pv_is_null(PyObject *self, PyObject *args)
static PyMethodDef _sr_apy_kemi_pv_Methods[] = {
{"get", sr_apy_kemi_f_pv_get, METH_VARARGS,
NAME " - pv get value"},
{"getw", sr_apy_kemi_f_pv_getw, METH_VARARGS,
NAME " - pv get value or <<null>>"},
{"seti", sr_apy_kemi_f_pv_seti, METH_VARARGS,
NAME " - pv set int value"},
{"sets", sr_apy_kemi_f_pv_sets, METH_VARARGS,

@ -275,7 +275,20 @@ static int sqlang_gettype(HSQUIRRELVM J, int idx)
/**
*
*/
static SQInteger sqlang_sr_pv_get(HSQUIRRELVM J)
static SQInteger sqlang_sr_get_str_null(HSQUIRRELVM J, int rmode)
{
if(rmode) {
sqlang_pushlstring(J, "<<null>>", 8);
return 1;
} else {
return 0;
}
}
/**
*
*/
static SQInteger sqlang_sr_pv_get_mode(HSQUIRRELVM J, int rmode)
{
str pvn;
pv_spec_t *pvs;
@ -287,24 +300,24 @@ static SQInteger sqlang_sr_pv_get(HSQUIRRELVM J)
pvn.s = (char*)sqlang_to_string(J, 0);
if(pvn.s==NULL || env_J->msg==NULL)
return 0;
return sqlang_sr_get_str_null(J, rmode);
pvn.len = strlen(pvn.s);
LM_DBG("pv get: %s\n", pvn.s);
pl = pv_locate_name(&pvn);
if(pl != pvn.len) {
LM_ERR("invalid pv [%s] (%d/%d)\n", pvn.s, pl, pvn.len);
return 0;
return sqlang_sr_get_str_null(J, rmode);
}
pvs = pv_cache_get(&pvn);
if(pvs==NULL) {
LM_ERR("cannot get pv spec for [%s]\n", pvn.s);
return 0;
return sqlang_sr_get_str_null(J, rmode);
}
memset(&val, 0, sizeof(pv_value_t));
if(pv_get_spec_value(env_J->msg, pvs, &val) != 0) {
LM_ERR("unable to get pv value for [%s]\n", pvn.s);
return 0;
return sqlang_sr_get_str_null(J, rmode);
}
if(val.flags&PV_VAL_NULL) {
sqlang_pushstring(J, NULL);
@ -318,6 +331,22 @@ static SQInteger sqlang_sr_pv_get(HSQUIRRELVM J)
return 1;
}
/**
*
*/
static SQInteger sqlang_sr_pv_get(HSQUIRRELVM J)
{
return sqlang_sr_pv_get_mode(J, 0);
}
/**
*
*/
static SQInteger sqlang_sr_pv_getw(HSQUIRRELVM J)
{
return sqlang_sr_pv_get_mode(J, 1);
}
/**
*
*/
@ -508,6 +537,7 @@ static SQInteger sqlang_sr_pv_is_null (HSQUIRRELVM J)
const SQRegFunction _sr_kemi_pv_J_Map[] = {
{ "get", sqlang_sr_pv_get, 2 /* 1 args */, NULL },
{ "getw", sqlang_sr_pv_getw, 2 /* 1 args */, NULL },
{ "seti", sqlang_sr_pv_seti, 3 /* 2 args */, NULL },
{ "sets", sqlang_sr_pv_sets, 4 /* 2 args */, NULL },
{ "unset", sqlang_sr_pv_unset, 2 /* 1 args */, NULL },
@ -1300,19 +1330,33 @@ int sr_kemi_sqlang_exec_func_ex(HSQUIRRELVM J, sr_kemi_t *ket)
break;
case 4:
if(ket->ptypes[0]==SR_KEMIP_STR
|| ket->ptypes[1]==SR_KEMIP_STR
|| ket->ptypes[2]==SR_KEMIP_STR
|| ket->ptypes[3]==SR_KEMIP_STR) {
&& ket->ptypes[1]==SR_KEMIP_STR
&& ket->ptypes[2]==SR_KEMIP_STR
&& ket->ptypes[3]==SR_KEMIP_STR) {
ret = ((sr_kemi_fmssss_f)(ket->func))(env_J->msg,
&vps[0].s, &vps[1].s, &vps[2].s, &vps[3].s);
return sr_kemi_sqlang_return_int(J, ket, ret);
} else if(ket->ptypes[0]==SR_KEMIP_STR
|| ket->ptypes[1]==SR_KEMIP_STR
|| ket->ptypes[2]==SR_KEMIP_INT
|| ket->ptypes[3]==SR_KEMIP_INT) {
&& ket->ptypes[1]==SR_KEMIP_STR
&& ket->ptypes[2]==SR_KEMIP_STR
&& ket->ptypes[3]==SR_KEMIP_INT) {
ret = ((sr_kemi_fmsssn_f)(ket->func))(env_J->msg,
&vps[0].s, &vps[1].s, &vps[2].s, vps[3].n);
return sr_kemi_sqlang_return_int(J, ket, ret);
} else if(ket->ptypes[0]==SR_KEMIP_STR
&& ket->ptypes[1]==SR_KEMIP_STR
&& ket->ptypes[2]==SR_KEMIP_INT
&& ket->ptypes[3]==SR_KEMIP_INT) {
ret = ((sr_kemi_fmssnn_f)(ket->func))(env_J->msg,
&vps[0].s, &vps[1].s, vps[2].n, vps[3].n);
return sr_kemi_sqlang_return_int(J, ket, ret);
} else if(ket->ptypes[0]==SR_KEMIP_INT
&& ket->ptypes[1]==SR_KEMIP_STR
&& ket->ptypes[2]==SR_KEMIP_STR
&& ket->ptypes[3]==SR_KEMIP_STR) {
ret = ((sr_kemi_fmnsss_f)(ket->func))(env_J->msg,
vps[0].n, &vps[1].s, &vps[2].s, &vps[3].s);
return sr_kemi_sqlang_return_int(J, ket, ret);
} else {
LM_ERR("invalid parameters for: %.*s\n",
fname->len, fname->s);
@ -1321,10 +1365,10 @@ int sr_kemi_sqlang_exec_func_ex(HSQUIRRELVM J, sr_kemi_t *ket)
break;
case 5:
if(ket->ptypes[0]==SR_KEMIP_STR
|| ket->ptypes[1]==SR_KEMIP_STR
|| ket->ptypes[2]==SR_KEMIP_STR
|| ket->ptypes[3]==SR_KEMIP_STR
|| ket->ptypes[4]==SR_KEMIP_STR) {
&& ket->ptypes[1]==SR_KEMIP_STR
&& ket->ptypes[2]==SR_KEMIP_STR
&& ket->ptypes[3]==SR_KEMIP_STR
&& ket->ptypes[4]==SR_KEMIP_STR) {
ret = ((sr_kemi_fmsssss_f)(ket->func))(env_J->msg,
&vps[0].s, &vps[1].s, &vps[2].s, &vps[3].s,
&vps[4].s);
@ -1337,11 +1381,11 @@ int sr_kemi_sqlang_exec_func_ex(HSQUIRRELVM J, sr_kemi_t *ket)
break;
case 6:
if(ket->ptypes[0]==SR_KEMIP_STR
|| ket->ptypes[1]==SR_KEMIP_STR
|| ket->ptypes[2]==SR_KEMIP_STR
|| ket->ptypes[3]==SR_KEMIP_STR
|| ket->ptypes[4]==SR_KEMIP_STR
|| ket->ptypes[5]==SR_KEMIP_STR) {
&& ket->ptypes[1]==SR_KEMIP_STR
&& ket->ptypes[2]==SR_KEMIP_STR
&& ket->ptypes[3]==SR_KEMIP_STR
&& ket->ptypes[4]==SR_KEMIP_STR
&& ket->ptypes[5]==SR_KEMIP_STR) {
ret = ((sr_kemi_fmssssss_f)(ket->func))(env_J->msg,
&vps[0].s, &vps[1].s, &vps[2].s, &vps[3].s,
&vps[4].s, &vps[5].s);

@ -1,131 +1,131 @@
# Microsoft Developer Studio Project File - Name="sqstdlib" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Static Library" 0x0104
CFG=sqstdlib - Win32 Release
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "sqstdlib.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "sqstdlib.mak" CFG="sqstdlib - Win32 Release"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "sqstdlib - Win32 Release" (based on "Win32 (x86) Static Library")
!MESSAGE "sqstdlib - Win32 Debug" (based on "Win32 (x86) Static Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_LocalPath ".."
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "sqstdlib - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
# ADD CPP /nologo /W3 /GX /O2 /I "..\include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
# ADD BASE RSC /l 0x410 /d "NDEBUG"
# ADD RSC /l 0x410 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:"..\lib\sqstdlib.lib"
!ELSEIF "$(CFG)" == "sqstdlib - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
# ADD BASE RSC /l 0x410 /d "_DEBUG"
# ADD RSC /l 0x410 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:"..\lib\sqstdlib.lib"
!ENDIF
# Begin Target
# Name "sqstdlib - Win32 Release"
# Name "sqstdlib - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\sqstdblob.cpp
# End Source File
# Begin Source File
SOURCE=.\sqstdio.cpp
# End Source File
# Begin Source File
SOURCE=.\sqstdmath.cpp
# End Source File
# Begin Source File
SOURCE=.\sqstdrex.cpp
# End Source File
# Begin Source File
SOURCE=.\sqstdstream.cpp
# End Source File
# Begin Source File
SOURCE=.\sqstdstring.cpp
# End Source File
# Begin Source File
SOURCE=.\sqstdaux.cpp
# End Source File
# Begin Source File
SOURCE=.\sqstdsystem.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=.\sqstdblobimpl.h
# End Source File
# Begin Source File
SOURCE=.\sqstdstream.h
# End Source File
# End Group
# End Target
# End Project
# Microsoft Developer Studio Project File - Name="sqstdlib" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Static Library" 0x0104
CFG=sqstdlib - Win32 Release
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "sqstdlib.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "sqstdlib.mak" CFG="sqstdlib - Win32 Release"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "sqstdlib - Win32 Release" (based on "Win32 (x86) Static Library")
!MESSAGE "sqstdlib - Win32 Debug" (based on "Win32 (x86) Static Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_LocalPath ".."
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "sqstdlib - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
# ADD CPP /nologo /W3 /GX /O2 /I "..\include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
# ADD BASE RSC /l 0x410 /d "NDEBUG"
# ADD RSC /l 0x410 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:"..\lib\sqstdlib.lib"
!ELSEIF "$(CFG)" == "sqstdlib - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
# ADD BASE RSC /l 0x410 /d "_DEBUG"
# ADD RSC /l 0x410 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:"..\lib\sqstdlib.lib"
!ENDIF
# Begin Target
# Name "sqstdlib - Win32 Release"
# Name "sqstdlib - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\sqstdblob.cpp
# End Source File
# Begin Source File
SOURCE=.\sqstdio.cpp
# End Source File
# Begin Source File
SOURCE=.\sqstdmath.cpp
# End Source File
# Begin Source File
SOURCE=.\sqstdrex.cpp
# End Source File
# Begin Source File
SOURCE=.\sqstdstream.cpp
# End Source File
# Begin Source File
SOURCE=.\sqstdstring.cpp
# End Source File
# Begin Source File
SOURCE=.\sqstdaux.cpp
# End Source File
# Begin Source File
SOURCE=.\sqstdsystem.cpp
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=.\sqstdblobimpl.h
# End Source File
# Begin Source File
SOURCE=.\sqstdstream.h
# End Source File
# End Group
# End Target
# End Project

@ -1,302 +1,302 @@
# Microsoft Developer Studio Project File - Name="squirrel" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Static Library" 0x0104
CFG=squirrel - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "squirrel.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "squirrel.mak" CFG="squirrel - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "squirrel - Win32 Release" (based on "Win32 (x86) Static Library")
!MESSAGE "squirrel - Win32 Debug" (based on "Win32 (x86) Static Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_LocalPath ".."
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "squirrel - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
# ADD CPP /nologo /W3 /GX /O2 /I "..\include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "GARBAGE_COLLECTOR" /YX /FD /c
# ADD BASE RSC /l 0x410 /d "NDEBUG"
# ADD RSC /l 0x410 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:"..\lib\squirrel.lib"
!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
# ADD BASE RSC /l 0x410 /d "_DEBUG"
# ADD RSC /l 0x410 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:"..\lib\squirrel.lib"
!ENDIF
# Begin Target
# Name "squirrel - Win32 Release"
# Name "squirrel - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\sqapi.cpp
!IF "$(CFG)" == "squirrel - Win32 Release"
!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"
# ADD CPP /YX"stdafx.h"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\sqbaselib.cpp
!IF "$(CFG)" == "squirrel - Win32 Release"
!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"
# ADD CPP /YX"stdafx.h"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\sqcompiler.cpp
!IF "$(CFG)" == "squirrel - Win32 Release"
!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"
# ADD CPP /YX"stdafx.h"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\sqdebug.cpp
!IF "$(CFG)" == "squirrel - Win32 Release"
!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"
# ADD CPP /YX"stdafx.h"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\sqfuncstate.cpp
!IF "$(CFG)" == "squirrel - Win32 Release"
!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"
# ADD CPP /YX"stdafx.h"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\sqlexer.cpp
!IF "$(CFG)" == "squirrel - Win32 Release"
!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"
# ADD CPP /YX"stdafx.h"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\sqmem.cpp
# End Source File
# Begin Source File
SOURCE=.\sqobject.cpp
!IF "$(CFG)" == "squirrel - Win32 Release"
!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"
# ADD CPP /YX"stdafx.h"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\sqstate.cpp
!IF "$(CFG)" == "squirrel - Win32 Release"
!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"
# ADD CPP /YX"stdafx.h"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\sqtable.cpp
!IF "$(CFG)" == "squirrel - Win32 Release"
!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"
# ADD CPP /YX"stdafx.h"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\sqclass.cpp
!IF "$(CFG)" == "squirrel - Win32 Release"
!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"
# ADD CPP /YX"stdafx.h"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\sqvm.cpp
!IF "$(CFG)" == "squirrel - Win32 Release"
!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"
# ADD CPP /YX"stdafx.h"
!ENDIF
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=.\sqarray.h
# End Source File
# Begin Source File
SOURCE=.\sqclosure.h
# End Source File
# Begin Source File
SOURCE=.\sqcompiler.h
# End Source File
# Begin Source File
SOURCE=.\sqfuncproto.h
# End Source File
# Begin Source File
SOURCE=.\sqfuncstate.h
# End Source File
# Begin Source File
SOURCE=.\sqlexer.h
# End Source File
# Begin Source File
SOURCE=.\sqobject.h
# End Source File
# Begin Source File
SOURCE=.\sqopcodes.h
# End Source File
# Begin Source File
SOURCE=.\sqpcheader.h
# End Source File
# Begin Source File
SOURCE=.\sqstate.h
# End Source File
# Begin Source File
SOURCE=.\sqstring.h
# End Source File
# Begin Source File
SOURCE=.\sqtable.h
# End Source File
# Begin Source File
SOURCE=.\squserdata.h
# End Source File
# Begin Source File
SOURCE=.\squtils.h
# End Source File
# Begin Source File
SOURCE=.\sqclass.h
# End Source File
# Begin Source File
SOURCE=.\sqvm.h
# End Source File
# End Group
# End Target
# End Project
# Microsoft Developer Studio Project File - Name="squirrel" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Static Library" 0x0104
CFG=squirrel - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "squirrel.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "squirrel.mak" CFG="squirrel - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "squirrel - Win32 Release" (based on "Win32 (x86) Static Library")
!MESSAGE "squirrel - Win32 Debug" (based on "Win32 (x86) Static Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_LocalPath ".."
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "squirrel - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
# ADD CPP /nologo /W3 /GX /O2 /I "..\include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "GARBAGE_COLLECTOR" /YX /FD /c
# ADD BASE RSC /l 0x410 /d "NDEBUG"
# ADD RSC /l 0x410 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:"..\lib\squirrel.lib"
!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
# ADD BASE RSC /l 0x410 /d "_DEBUG"
# ADD RSC /l 0x410 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo /out:"..\lib\squirrel.lib"
!ENDIF
# Begin Target
# Name "squirrel - Win32 Release"
# Name "squirrel - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\sqapi.cpp
!IF "$(CFG)" == "squirrel - Win32 Release"
!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"
# ADD CPP /YX"stdafx.h"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\sqbaselib.cpp
!IF "$(CFG)" == "squirrel - Win32 Release"
!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"
# ADD CPP /YX"stdafx.h"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\sqcompiler.cpp
!IF "$(CFG)" == "squirrel - Win32 Release"
!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"
# ADD CPP /YX"stdafx.h"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\sqdebug.cpp
!IF "$(CFG)" == "squirrel - Win32 Release"
!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"
# ADD CPP /YX"stdafx.h"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\sqfuncstate.cpp
!IF "$(CFG)" == "squirrel - Win32 Release"
!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"
# ADD CPP /YX"stdafx.h"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\sqlexer.cpp
!IF "$(CFG)" == "squirrel - Win32 Release"
!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"
# ADD CPP /YX"stdafx.h"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\sqmem.cpp
# End Source File
# Begin Source File
SOURCE=.\sqobject.cpp
!IF "$(CFG)" == "squirrel - Win32 Release"
!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"
# ADD CPP /YX"stdafx.h"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\sqstate.cpp
!IF "$(CFG)" == "squirrel - Win32 Release"
!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"
# ADD CPP /YX"stdafx.h"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\sqtable.cpp
!IF "$(CFG)" == "squirrel - Win32 Release"
!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"
# ADD CPP /YX"stdafx.h"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\sqclass.cpp
!IF "$(CFG)" == "squirrel - Win32 Release"
!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"
# ADD CPP /YX"stdafx.h"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\sqvm.cpp
!IF "$(CFG)" == "squirrel - Win32 Release"
!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"
# ADD CPP /YX"stdafx.h"
!ENDIF
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=.\sqarray.h
# End Source File
# Begin Source File
SOURCE=.\sqclosure.h
# End Source File
# Begin Source File
SOURCE=.\sqcompiler.h
# End Source File
# Begin Source File
SOURCE=.\sqfuncproto.h
# End Source File
# Begin Source File
SOURCE=.\sqfuncstate.h
# End Source File
# Begin Source File
SOURCE=.\sqlexer.h
# End Source File
# Begin Source File
SOURCE=.\sqobject.h
# End Source File
# Begin Source File
SOURCE=.\sqopcodes.h
# End Source File
# Begin Source File
SOURCE=.\sqpcheader.h
# End Source File
# Begin Source File
SOURCE=.\sqstate.h
# End Source File
# Begin Source File
SOURCE=.\sqstring.h
# End Source File
# Begin Source File
SOURCE=.\sqtable.h
# End Source File
# Begin Source File
SOURCE=.\squserdata.h
# End Source File
# Begin Source File
SOURCE=.\squtils.h
# End Source File
# Begin Source File
SOURCE=.\sqclass.h
# End Source File
# Begin Source File
SOURCE=.\sqvm.h
# End Source File
# End Group
# End Target
# End Project

@ -10,9 +10,9 @@
<!-- Module User's Guide -->
<chapter>
<title>&adminguide;</title>
<section>
<title>Overview</title>
<para>
@ -24,7 +24,7 @@
</para>
<para>
Note that after invoking the asynchronous operation, the processing
will continue later in another application process. Therefore variables
will continue later in another application process. Therefore variables
stored in private memory should not be used, try to use shared memory if you
want to get values after the processing is resumed (e.g., $avp(...),
$xavp(...), $shv(...), htable $sht(...)).
@ -72,7 +72,7 @@
<title><varname>workers</varname> (int)</title>
<para>
Number of worker processes to be started to handle the asynchronous
tasks for async_route() and async_sleep().
tasks for async_route() and async_sleep().
</para>
<para>
<emphasis>
@ -124,8 +124,11 @@ modparam("async", "workers", 2)
<title><function>async_route</function> usage</title>
<programlisting format="linespecific">
...
async_route("RESUME", "4");
...
request_route {
...
async_route("RESUME", "4");
...
}
route[RESUME] {
send_reply("404", "Not found");
exit;
@ -184,7 +187,7 @@ exit;
<title><function>async_workers</function> usage</title>
<programlisting format="linespecific">
...
; Enable 8 worker processes used by async and other modules
# Enable 8 worker processes used by async and other modules
async_workers=8
...
</programlisting>
@ -212,8 +215,11 @@ async_workers=8
<title><function>async_task_route</function> usage</title>
<programlisting format="linespecific">
...
async_task_route("RESUME");
...
request_route {
...
async_task_route("RESUME");
...
}
route[RESUME] {
t_relay();
exit;
@ -224,4 +230,3 @@ route[RESUME] {
</section>
</section>
</chapter>

@ -39,7 +39,7 @@ typedef enum auth_diam_result {
INVALID_PASSWORD, /*!< Invalid password */
USER_UNKNOWN, /*!< User non existant */
ERROR, /*!< Error occurred, a reply has been sent out,
return 0 to the openser core */
return 0 to the kamailio core */
AUTHORIZED, /*!< Authorized. If returned by pre_auth,
no digest authorization necessary */
DO_AUTHORIZATION, /*!< Can only be returned by pre_auth. */

@ -11,6 +11,14 @@ SSL_BUILDER=$(shell \
if pkg-config --exists libssl; then \
echo 'pkg-config libssl'; \
fi)
ifneq ($(SSL_BUILDER),)
SSL_BUILDER+=$(shell \
if pkg-config --exists libcrypto; then \
echo 'libcrypto'; \
fi)
endif
endif
ifneq ($(SSL_BUILDER),)

@ -97,6 +97,9 @@ static int init_target_opts(){
}
static void reset_prefix_opts(){
memset(&(target_options[PO_MAX_TARGETS].value),'\0', sizeof(union opt_data));
prefix_options[PO_MAX_TARGETS].visited = 0;
prefix_options[PO_MAX_TARGETS].no_elems = 0;
prefix_options[PO_MAX_TARGETS].value.int_data=-1;
}

@ -353,7 +353,7 @@ int load_route_data_db(struct route_data_t * rd) {
}
}
int n = 0;
boolean query_done = false;
crboolean query_done = crfalse;
do {
LM_DBG("loading, cycle %d", n++);
for (i = 0; i < RES_ROW_N(res); ++i) {
@ -421,7 +421,7 @@ int load_route_data_db(struct route_data_t * rd) {
}
if(RES_ROW_N(prob_res) == 0) {
LM_ERR("Carrierroute db table contains route(s) with only 0 probability.\n");
query_done = true;
query_done = crtrue;
}
carrierroute_dbf.free_result(carrierroute_dbh, prob_res);
prob_res = NULL;

@ -89,8 +89,8 @@ int load_route_data_db (struct route_data_t * rd);
int load_user_carrier(str * user, str * domain);
typedef enum {
false = 0,
true = 1
} boolean;
crfalse = 0,
crtrue = 1
} crboolean;
#endif

@ -801,11 +801,10 @@ static int w_check_route_exists(struct sip_msg *msg, char *route)
static int w_route_exists(struct sip_msg *msg, char *route)
{
struct run_act_ctx ctx;
int newroute, backup_rt, ret;
int newroute, ret;
str s;
if (fixup_get_svalue(msg, (gparam_p) route, &s) != 0)
{
if (fixup_get_svalue(msg, (gparam_p) route, &s) != 0) {
LM_ERR("invalid route parameter\n");
return -1;
}
@ -814,12 +813,8 @@ static int w_route_exists(struct sip_msg *msg, char *route)
if (newroute<0) {
return -1;
}
backup_rt = get_route_type();
set_route_type(REQUEST_ROUTE);
init_run_actions_ctx(&ctx);
ret = run_top_route(main_rt.rlist[newroute], msg, &ctx);
set_route_type(backup_rt);
ret=run_actions(&ctx, main_rt.rlist[newroute], msg);
if (ctx.run_flags & EXIT_R_F) {
return 0;
}

@ -110,7 +110,7 @@
#!ifdef WITH_MYSQL
# - database URL - used to connect to database server by modules such
# as: auth_db, acc, usrloc, a.s.o.
#!define DBURL "mysql://openser:openserrw@localhost/openser"
#!define DBURL "mysql://kamailio:kamailiorw@localhost/kamailio"
#!endif
#!ifdef WITH_MULTIDOMAIN
# - the value for 'use_domain' parameters

@ -15,7 +15,7 @@
<title>Functions</title>
<section id="cnt_inc">
<section id="counters.f.cnt_inc">
<title>
<function>cnt_inc([group.]name)</function>
</title>
@ -43,7 +43,7 @@ route {
</example>
</section>
<section id="cnt_add">
<section id="counters.f.cnt_add">
<title>
<function>cnt_add([group.]name, number)</function>
</title>
@ -69,7 +69,7 @@ route {
</example>
</section>
<section id="cnt_reset">
<section id="counters.f.cnt_reset">
<title>
<function>cnt_reset([group.]name)</function>
</title>

@ -12,7 +12,7 @@
</sectioninfo>
<title>Parameters</title>
<section id="scrip_counter">
<section id="counters.p.scrip_counter">
<title><varname>script_counter</varname></title>
<para>
Define a new counter that can be used from the script.
@ -40,7 +40,7 @@ modparam("counters", "script_counter", "test.x:another example") # test.x
</example>
</section>
<section id="scrip_cnt_grp_name">
<section id="counters.p.scrip_cnt_grp_name">
<title><varname>script_cnt_grp_name</varname></title>
<para>
Group name that will be used for the counters defined

@ -12,7 +12,7 @@
</sectioninfo>
<title>RPC Commands</title>
<section id="cnt.r.get">
<section id="counters.rpc.cnt.get">
<title> <function>cnt.get</function></title>
<para>
Get the value of the counter identified by group.counter_name.
@ -28,7 +28,7 @@
</example>
</section>
<section id="cnt.r.reset">
<section id="counters.rpc.cnt.reset">
<title> <function>cnt.reset</function></title>
<para>
Resets the counter identified by group.counter_name.
@ -44,7 +44,7 @@
</example>
</section>
<section id="cnt.r.list_groups">
<section id="counters.rpc.cnt.list_groups">
<title> <function>cnt.list_groups</function></title>
<para>
Lists all the declared counter groups.
@ -60,14 +60,14 @@
</example>
</section>
<section id="cnt.r.grps_list">
<section id="counters.rpc.cnt.grps_list">
<title> <function>cnt.grps_list</function></title>
<para>
Alias to cnt.list_groups.
</para>
</section>
<section id="cnt.r.list_vars">
<section id="counters.rpc.cnt.list_vars">
<title> <function>cnt.list_vars</function></title>
<para>
Lists all the names of all the counters belonging to the
@ -84,14 +84,14 @@
</example>
</section>
<section id="cnt.r.var_list">
<section id="counters.rpc.cnt.var_list">
<title> <function>cnt.var_list</function></title>
<para>
Alias to cnt.list_vars.
</para>
</section>
<section id="cnt.r.get_vars">
<section id="counters.rpc.cnt.get_vars">
<title> <function>cnt.get_vars</function></title>
<para>
Lists all the counter names and their values in the
@ -108,14 +108,14 @@
</example>
</section>
<section id="cnt.r.grp_get_all">
<section id="counters.rpc.cnt.grp_get_all">
<title> <function>cnt.grp_get_all</function></title>
<para>
Alias to cnt.get_vars.
</para>
</section>
<section id="cnt.r.help">
<section id="counters.rpc.cnt.help">
<title> <function>cnt.help</function></title>
<para>
Displays the counter description.

@ -828,7 +828,7 @@ static inline int db_float2ldap_str(struct sbuf* buf, db_fld_t* fld)
}
static inline int db_double2ldap_str(struct sbuf* buf, db_fld_t* fld)
/*static inline int db_double2ldap_str(struct sbuf* buf, db_fld_t* fld)
{
char tmp[16];
int len;
@ -839,7 +839,7 @@ static inline int db_double2ldap_str(struct sbuf* buf, db_fld_t* fld)
return -1;
}
return sb_add(buf, tmp, len);
}
}*/
static inline int ld_db2ldap(struct sbuf* buf, db_fld_t* fld) {
struct ld_fld* lfld;

@ -1,6 +1,4 @@
/*
* $Id$
*
* Generic db cluster module interface
*
* Copyright (C) 2012 Daniel-Constantin Mierla (asipto.com)

@ -1,6 +1,4 @@
/*
* $Id$
*
* DB CLuster core functions
*
* Copyright (C) 2012 Daniel-Constantin Mierla (asipto.com)

@ -1,6 +1,4 @@
/*
* $Id$
*
* DB CLuster core functions
*
* Copyright (C) 2012 Daniel-Constantin Mierla (asipto.com)

@ -1,6 +1,4 @@
/*
* $Id$
*
* DB CLuster core functions
*
* Copyright (C) 2012 Daniel-Constantin Mierla (asipto.com)

@ -1,6 +1,4 @@
/*
* $Id$
*
* DB CLuster core functions
*
* Copyright (C) 2012 Daniel-Constantin Mierla (asipto.com)

@ -316,7 +316,9 @@ int db_mongodb_get_columns(const db1_con_t* _h, db1_res_t* _r)
int col;
db_mongodb_result_t *mgres;
bson_iter_t riter;
#if MONGOC_CHECK_VERSION(1, 5, 0)
bson_iter_t titer;
#endif
bson_iter_t citer;
bson_t *cdoc;
const char *colname;
@ -360,6 +362,7 @@ int db_mongodb_get_columns(const db1_con_t* _h, db1_res_t* _r)
}
if(cdocproj == 1) {
#if MONGOC_CHECK_VERSION(1, 5, 0)
if (!bson_iter_init (&titer, cdoc)) {
LM_ERR("failed to initialize columns iterator\n");
return -3;
@ -373,6 +376,12 @@ int db_mongodb_get_columns(const db1_con_t* _h, db1_res_t* _r)
LM_ERR("failed to init projection iterator\n");
return -3;
}
#else
if (!bson_iter_init (&citer, cdoc)) {
LM_ERR("failed to initialize columns iterator\n");
return -3;
}
#endif
} else {
if (!bson_iter_init (&citer, cdoc)) {
LM_ERR("failed to initialize columns iterator\n");
@ -506,7 +515,9 @@ static int db_mongodb_convert_bson(const db1_con_t* _h, db1_res_t* _r,
const char *colname;
bson_type_t coltype;
bson_iter_t riter;
#if MONGOC_CHECK_VERSION(1, 5, 0)
bson_iter_t titer;
#endif
bson_iter_t citer;
bson_iter_t *piter;
db_val_t* dval;
@ -527,6 +538,7 @@ static int db_mongodb_convert_bson(const db1_con_t* _h, db1_res_t* _r,
}
} else {
cdoc = (bson_t*)mgres->colsdoc;
#if MONGOC_CHECK_VERSION(1, 5, 0)
if (!bson_iter_init (&titer, cdoc)) {
LM_ERR("failed to initialize columns iterator\n");
return -3;
@ -540,6 +552,12 @@ static int db_mongodb_convert_bson(const db1_con_t* _h, db1_res_t* _r,
LM_ERR("failed to init projection iterator\n");
return -3;
}
#else
if (!bson_iter_init (&citer, cdoc)) {
LM_ERR("failed to initialize columns iterator\n");
return -3;
}
#endif
}
if(mgres->colsdoc) {
@ -612,7 +630,13 @@ static int db_mongodb_convert_bson(const db1_con_t* _h, db1_res_t* _r,
break;
case BSON_TYPE_UTF8:
VAL_STRING(dval) = (char*)bson_iter_utf8 (piter, &i32tmp);
{
char* rstring = (char*)bson_iter_utf8 (piter, &i32tmp);
if(db_str2val(DB1_STRING, dval, rstring, i32tmp, 1)<0) {
LM_ERR("failed to convert utf8 value\n");
return -5;
}
}
break;
case BSON_TYPE_OID:
@ -753,6 +777,7 @@ static int db_mongodb_store_result(const db1_con_t* _h, db1_res_t** _r)
km_mongodb_con_t *mgcon;
db_mongodb_result_t *mgres;
const bson_t *itdoc;
bson_error_t error;
mgcon = MONGODB_CON(_h);
if(!_r) {
@ -777,7 +802,11 @@ static int db_mongodb_store_result(const db1_con_t* _h, db1_res_t** _r)
if(!mongoc_cursor_more (mgres->cursor)
|| !mongoc_cursor_next (mgres->cursor, &itdoc)
|| !itdoc) {
LM_DBG("no result from mongodb\n");
if (mongoc_cursor_error (mgres->cursor, &error)) {
LM_DBG("An error occurred: %s\n", error.message);
} else {
LM_DBG("no result from mongodb\n");
}
return 0;
}
/* first document linked internally in result to get columns */
@ -859,7 +888,9 @@ int db_mongodb_query(const db1_con_t* _h, const db_key_t* _k, const db_op_t* _op
km_mongodb_con_t *mgcon;
mongoc_client_t *client;
bson_t *seldoc = NULL;
#if MONGOC_CHECK_VERSION(1, 5, 0)
bson_t bcols;
#endif
char *cname;
char b1;
char *jstr;
@ -939,23 +970,31 @@ int db_mongodb_query(const db1_con_t* _h, const db_key_t* _k, const db_op_t* _op
LM_ERR("cannot initialize columns bson document\n");
goto error;
}
#if MONGOC_CHECK_VERSION(1, 5, 0)
if(!bson_append_document_begin (mgcon->colsdoc, "projection", 10,
&bcols)) {
LM_ERR("failed to start projection of fields\n");
goto error;
}
#endif
for(i = 0; i < _nc; i++) {
#if MONGOC_CHECK_VERSION(1, 5, 0)
if(!bson_append_int32(&bcols, _c[i]->s, _c[i]->len, 1))
#else
if(!bson_append_int32(mgcon->colsdoc, _c[i]->s, _c[i]->len, 1))
#endif
{
LM_ERR("failed to append int to columns bson %.*s = %d [%d]\n",
_c[i]->len, _c[i]->s, 1, i);
goto error;
}
}
#if MONGOC_CHECK_VERSION(1, 5, 0)
if(!bson_append_document_end (mgcon->colsdoc, &bcols)) {
LM_ERR("failed to end projection of fields\n");
goto error;
}
#endif
if(is_printable(L_DBG)) {
jstr = bson_as_json (mgcon->colsdoc, NULL);
LM_DBG("columns filter: %s\n", jstr);

@ -32,18 +32,13 @@ static int mod_init(void);
SV* vdbmod;
static int db_perlvdb_bind_api(db_func_t *dbb);
/*
* Perl virtual database module interface
*/
static cmd_export_t cmds[] = {
{"db_use_table", (cmd_function)perlvdb_use_table, 2, 0, 0, 0},
{"db_init", (cmd_function)perlvdb_db_init, 1, 0, 0, 0},
{"db_close", (cmd_function)perlvdb_db_close, 2, 0, 0, 0},
{"db_insert", (cmd_function)perlvdb_db_insert, 2, 0, 0, 0},
{"db_update", (cmd_function)perlvdb_db_update, 2, 0, 0, 0},
{"db_delete", (cmd_function)perlvdb_db_delete, 2, 0, 0, 0},
{"db_query", (cmd_function)perlvdb_db_query, 2, 0, 0, 0},
{"db_free_result", (cmd_function)perlvdb_db_free_result, 2, 0, 0, 0},
{"db_bind_api", (cmd_function)db_perlvdb_bind_api, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0}
};
@ -75,10 +70,32 @@ struct module_exports exports = {
static int mod_init(void)
{
if (!module_loaded("perl")) {
LM_CRIT("perl module not loaded. Exiting.\n");
if (!module_loaded("app_perl")) {
LM_CRIT("app_perl module not loaded. Exiting.\n");
return -1;
}
return 0;
}
static int db_perlvdb_bind_api(db_func_t *dbb)
{
if(dbb==NULL)
return -1;
memset(dbb, 0, sizeof(db_func_t));
dbb->use_table = perlvdb_use_table;
dbb->init = perlvdb_db_init;
dbb->close = perlvdb_db_close;
dbb->query = perlvdb_db_query;
dbb->fetch_result = 0;
dbb->raw_query = 0;
dbb->free_result = perlvdb_db_free_result;
dbb->insert = perlvdb_db_insert;
dbb->delete = perlvdb_db_delete;
dbb->update = perlvdb_db_update;
dbb->replace = perlvdb_db_replace;
return 0;
}

@ -31,7 +31,7 @@
operations is supported.
</para>
<para>
Modules can be configured to use the perlvdb module as
Modules can be configured to use the db_perlvdb module as
database backend using the db_url_parameter:
</para>
<programlisting>
@ -39,7 +39,7 @@ modparam("acc", "db_url", "perlvdb:Kamailio::VDB::Adapter::AccountingSIPtrace")
</programlisting>
<para>
This configuration options tells acc module that it should use the
perlvdb module which will in turn use the Perl class
db_perlvdb module which will in turn use the Perl class
Kamailio::VDB::Adapter::AccountingSIPtrace
to relay the database requests.
</para>
@ -53,7 +53,7 @@ modparam("acc", "db_url", "perlvdb:Kamailio::VDB::Adapter::AccountingSIPtrace")
The following modules must be loaded before this module:
<itemizedlist>
<listitem>
<para><emphasis>perl</emphasis> -- Perl module</para>
<para><emphasis>app_perl</emphasis> -- Perl Application module</para>
</listitem>
</itemizedlist>
</para>
@ -66,7 +66,7 @@ modparam("acc", "db_url", "perlvdb:Kamailio::VDB::Adapter::AccountingSIPtrace")
<itemizedlist>
<listitem>
<para>
<emphasis>None</emphasis> (Besides the ones mentioned in the perl
<emphasis>None</emphasis> (Besides the ones mentioned in the app_perl
module documentation).
</para>
</listitem>

@ -30,7 +30,7 @@
</section>
<section><title>Base class Kamailio::VDB</title>
<para>
A client module has to be configured to use the perlvdb module in conjunction
A client module has to be configured to use the db_perlvdb module in conjunction
with a Perl class to provide the functions. The configured class needs to
inherit from the base class <literal role="code">Kamailio::VDB</literal>.
</para>

@ -33,7 +33,7 @@
/* Converts a set of pairs to perl SVs.
* For insert, and update (second half)
*/
AV *pairs2perlarray(db_key_t* keys, db_val_t* vals, int n) {
AV *pairs2perlarray(const db_key_t* keys, const db_val_t* vals, const int n) {
AV *array = newAV();
SV *element;
@ -50,7 +50,7 @@ AV *pairs2perlarray(db_key_t* keys, db_val_t* vals, int n) {
/* Converts a set of cond's to perl SVs.
* For delete, update (first half), query
*/
AV *conds2perlarray(db_key_t* keys, db_op_t* ops, db_val_t* vals, int n) {
AV *conds2perlarray(const db_key_t* keys, const db_op_t* ops, const db_val_t* vals, const int n) {
AV *array = newAV();
SV *element = NULL;
int i = 0;
@ -80,7 +80,7 @@ AV *conds2perlarray(db_key_t* keys, db_op_t* ops, db_val_t* vals, int n) {
/* Converts a set of key names to a perl array.
* Needed in query.
*/
AV *keys2perlarray(db_key_t* keys, int n) {
AV *keys2perlarray(const db_key_t* keys, const int n) {
AV *array = newAV();
SV *element;
int i;
@ -92,7 +92,7 @@ AV *keys2perlarray(db_key_t* keys, int n) {
return array;
}
SV *valdata(db_val_t* val) {
SV *valdata(const db_val_t* val) {
SV *data = &PL_sv_undef;
const char* stringval;
@ -148,7 +148,7 @@ SV *valdata(db_val_t* val) {
return data;
}
SV *val2perlval(db_val_t* val) {
SV *val2perlval(const db_val_t* val) {
SV* retval;
SV *class;
@ -167,7 +167,7 @@ SV *val2perlval(db_val_t* val) {
}
SV *pair2perlpair(db_key_t key, db_val_t* val) {
SV *pair2perlpair(const db_key_t key, const db_val_t* val) {
SV* retval;
SV *class;
@ -190,7 +190,7 @@ SV *pair2perlpair(db_key_t key, db_val_t* val) {
}
SV *cond2perlcond(db_key_t key, db_op_t op, db_val_t* val) {
SV *cond2perlcond(const db_key_t key, const db_op_t op, const db_val_t* val) {
SV* retval;
SV *class;
@ -290,11 +290,9 @@ int perlresult2dbres(SV *perlres, db1_res_t **r) {
currentstring = SvPV(d1, len);
charbuf = pkg_malloc(len+1);
strncpy(charbuf, currentstring, len+1);
(*r)->col.names[i]->s = charbuf;
(*r)->col.names[i]->len = strlen(charbuf);
(*r)->col.names[i] = (db_key_t)charbuf;
SvREFCNT_dec(d1);
}
rowarrayref = perlvdb_perlmethod(perlres, PERL_VDB_ROWSMETHOD,
@ -405,13 +403,11 @@ int perlresult2dbres(SV *perlres, db1_res_t **r) {
}
end:
av_undef(colarray);
av_undef(rowarray);
if (colarray) av_undef(colarray);
if (rowarray) av_undef(rowarray);
return retval;
error:
LM_CRIT("broken result set. Exiting, leaving Kamailio in unknown state.\n");
return -1;
}

@ -44,21 +44,21 @@
/* Converts a set of pairs to perl SVs.
* For insert, and update (second half)
*/
AV *pairs2perlarray(db_key_t* keys, db_val_t* vals, int n);
AV *pairs2perlarray(const db_key_t* keys, const db_val_t* vals, const int n);
/* Converts a set of cond's to perl SVs.
* For delete, update (first half), query
*/
AV *conds2perlarray(db_key_t* keys, db_op_t* ops, db_val_t* vals, int n);
AV *conds2perlarray(const db_key_t* keys, const db_op_t* ops, const db_val_t* vals, const int n);
/* Converts a set of key names to a perl array.
* Needed in query.
*/
AV *keys2perlarray(db_key_t* keys, int n);
AV *keys2perlarray(const db_key_t* keys, const int n);
SV *val2perlval(db_val_t* val);
SV *pair2perlpair(db_key_t key, db_val_t* val);
SV *cond2perlcond(db_key_t key, db_op_t op, db_val_t* val);
SV *val2perlval(const db_val_t* val);
SV *pair2perlpair(const db_key_t key, const db_val_t* val);
SV *cond2perlcond(const db_key_t key, const db_op_t op, const db_val_t* val);
int perlresult2dbres(SV *perlres, db1_res_t **r);

@ -53,10 +53,10 @@ long IV2int(SV *in) {
/*
* Returns the class part of the URI
*/
char *parseurl(const char* url) {
char *parseurl(const str* url) {
char *cn;
cn = strchr(url, ':') + 1;
cn = strchr(url->s, ':') + 1;
if (strlen(cn) > 0)
return cn;
else
@ -76,7 +76,7 @@ SV *newvdbobj(const char* cn) {
return obj;
}
SV *getobj(db1_con_t *con) {
SV *getobj(const db1_con_t *con) {
return ((SV*)CON_TAIL(con));
}
@ -105,7 +105,7 @@ int checkobj(SV* obj) {
* Initialize database module
* No function should be called before this
*/
db1_con_t* perlvdb_db_init(const char* url) {
db1_con_t* perlvdb_db_init(const str* url) {
db1_con_t* res;
char *cn;
@ -179,8 +179,8 @@ void perlvdb_db_close(db1_con_t* h) {
* v: values of the keys
* n: number of key=value pairs
*/
int perlvdb_db_insertreplace(db1_con_t* h, db_key_t* k, db_val_t* v,
int n, char *insertreplace) {
int perlvdb_db_insertreplace(const db1_con_t* h, const db_key_t* k, const db_val_t* v,
const int n, char *insertreplace) {
AV *arr;
SV *arrref;
SV *ret;
@ -195,14 +195,15 @@ int perlvdb_db_insertreplace(db1_con_t* h, db_key_t* k, db_val_t* v,
return IV2int(ret);
}
int perlvdb_db_insert(db1_con_t* h, db_key_t* k, db_val_t* v, int n) {
int perlvdb_db_insert(const db1_con_t* h, const db_key_t* k, const db_val_t* v, const int n) {
return perlvdb_db_insertreplace(h, k, v, n, PERL_VDB_INSERTMETHOD);
}
/*
* Just like insert, but replace the row if it exists
*/
int perlvdb_db_replace(db1_con_t* h, db_key_t* k, db_val_t* v, int n) {
int perlvdb_db_replace(const db1_con_t* h, const db_key_t* k, const db_val_t* v,
const int n, const int un, const int m) {
return perlvdb_db_insertreplace(h, k, v, n, PERL_VDB_REPLACEMETHOD);
}
@ -214,8 +215,8 @@ int perlvdb_db_replace(db1_con_t* h, db_key_t* k, db_val_t* v, int n) {
* v: values of the keys that must match
* n: number of key=value pairs
*/
int perlvdb_db_delete(db1_con_t* h, db_key_t* k, db_op_t* o, db_val_t* v,
int n) {
int perlvdb_db_delete(const db1_con_t* h, const db_key_t* k, const db_op_t* o,
const db_val_t* v, const int n) {
AV *arr;
SV *arrref;
SV *ret;
@ -242,8 +243,9 @@ int perlvdb_db_delete(db1_con_t* h, db_key_t* k, db_op_t* o, db_val_t* v,
* _n: number of key=value pairs
* _un: number of columns to update
*/
int perlvdb_db_update(db1_con_t* h, db_key_t* k, db_op_t* o, db_val_t* v,
db_key_t* uk, db_val_t* uv, int n, int un) {
int perlvdb_db_update(const db1_con_t* h, const db_key_t* k, const db_op_t* o,
const db_val_t* v, const db_key_t* uk, const db_val_t* uv,
const int n, const int un) {
AV *condarr;
AV *updatearr;
@ -280,9 +282,9 @@ int perlvdb_db_update(db1_con_t* h, db_key_t* k, db_op_t* o, db_val_t* v,
* nc: number of columns to return
* o: order by the specified column
*/
int perlvdb_db_query(db1_con_t* h, db_key_t* k, db_op_t* op, db_val_t* v,
db_key_t* c, int n, int nc,
db_key_t o, db1_res_t** r) {
int perlvdb_db_query(const db1_con_t* h, const db_key_t* k, const db_op_t* op,
const db_val_t* v, const db_key_t* c, const int n, const int nc,
const db_key_t o, db1_res_t** r) {
AV *condarr;

@ -38,7 +38,7 @@
* Initialize/close database module
* No function should be called before/after this
*/
db1_con_t* perlvdb_db_init(const char* _url);
db1_con_t* perlvdb_db_init(const str* _url);
void perlvdb_db_close(db1_con_t* h);
/*
@ -47,16 +47,18 @@ void perlvdb_db_close(db1_con_t* h);
*/
int perlvdb_use_table(db1_con_t* h, const str* t);
int perlvdb_db_insert(db1_con_t* h, db_key_t* k, db_val_t* v, int n);
int perlvdb_db_replace(db1_con_t* h, db_key_t* k, db_val_t* v, int n);
int perlvdb_db_delete(db1_con_t* h, db_key_t* k, db_op_t* o, db_val_t* v, int n);
int perlvdb_db_update(db1_con_t* h, db_key_t* k, db_op_t* o, db_val_t* v,
db_key_t* uk, db_val_t* uv, int n, int un);
int perlvdb_db_query(db1_con_t* h, db_key_t* k, db_op_t* op, db_val_t* v,
db_key_t* c, int n, int nc,
db_key_t o, db1_res_t** r);
int perlvdb_db_insert(const db1_con_t* h, const db_key_t* k, const db_val_t* v, const int n);
int perlvdb_db_replace(const db1_con_t* h, const db_key_t* k, const db_val_t* v,
const int n, const int un, const int m);
int perlvdb_db_delete(const db1_con_t* h, const db_key_t* k, const db_op_t* o,
const db_val_t* v, const int n);
int perlvdb_db_update(const db1_con_t* h, const db_key_t* k, const db_op_t* o,
const db_val_t* v, const db_key_t* uk, const db_val_t* uv,
const int n, const int un);
int perlvdb_db_query(const db1_con_t* h, const db_key_t* k, const db_op_t* op,
const db_val_t* v, const db_key_t* c, const int n, const int nc,
const db_key_t o, db1_res_t** r);
int perlvdb_db_free_result(db1_con_t* _h, db1_res_t* _r);
#endif /* _PERLVDBFUNC_H */

@ -1,12 +1,11 @@
#
# $Id$
#
# simple quick-start config script with dbtext
#
# ----------- global configuration parameters ------------------------
#debug=9 # debug level (cmd line: -dddddddddd)
#debug=3 # debug level (cmd line: -ddd)
#fork=yes
#log_stderror=no # (cmd line: -E)
@ -30,7 +29,7 @@ loadmodule "modules/maxfwd/maxfwd.so"
loadmodule "modules/usrloc/usrloc.so"
loadmodule "modules/registrar/registrar.so"
loadmodule "modules/textops/textops.so"
loadmodule "modules/textops/mi_fifo.so"
loadmodule "modules/jonrpcs/jsonrpcs.so"
# modules for digest authentication
loadmodule "modules/auth/auth.so"
@ -38,15 +37,11 @@ loadmodule "modules/auth_db/auth_db.so"
# ----------------- setting module-specific parameters ---------------
# -- mi_fifo params --
modparam("mi_fifo", "fifo_name", "/tmp/openser_fifo")
# -- usrloc params --
# use dbtext database for persistent storage
modparam("usrloc", "db_mode", 2)
modparam("usrloc|auth_db", "db_url", "dbtext:///tmp/openserdb")
modparam("usrloc|auth_db", "db_url", "db_text:///tmp/kamailiodb")
# -- auth params --
#

@ -1945,7 +1945,7 @@ static inline void internal_rpc_print_dlg(rpc_t *rpc, void *c, dlg_cell_t *dlg,
"socket", dlg->bind_addr[DLG_CALLEE_LEG] ? &dlg->bind_addr[DLG_CALLEE_LEG]->sock_str : &empty_str);
if (rpc->struct_add(h, "[", "profiles", &sh) < 0) goto error;
for (pl = dlg->profile_links ; pl ; pl=pl->next) {
for (pl = dlg->profile_links ; pl && (dlg->state<DLG_STATE_DELETED) ; pl=pl->next) {
if (pl->profile->has_value) {
rpc->array_add(sh, "{", &ssh);
rpc->struct_add(ssh, "S", pl->profile->name.s, &pl->hash_linker.value);
@ -1955,7 +1955,7 @@ static inline void internal_rpc_print_dlg(rpc_t *rpc, void *c, dlg_cell_t *dlg,
}
if (rpc->struct_add(h, "[", "variables", &sh) < 0) goto error;
for(var=dlg->vars ; var ; var=var->next) {
for(var=dlg->vars ; var && (dlg->state<DLG_STATE_DELETED) ; var=var->next) {
rpc->array_add(sh, "{", &ssh);
rpc->struct_add(ssh, "S", var->key.s, &var->value);
}

@ -73,7 +73,8 @@ static int dlg_cseq_prepare_msg(sip_msg_t *msg)
return 1;
}
if (parse_headers(msg, HDR_CSEQ_F, 0)==-1) {
if((!msg->cseq && (parse_headers(msg,HDR_CSEQ_F,0)<0 || !msg->cseq))
|| !msg->cseq->parsed){
LM_DBG("parsing cseq header failed\n");
return 2;
}

@ -426,6 +426,8 @@ static int load_dialog_info_from_db(int dlg_hash_size, int fetch_num_rows)
srjson_DestroyDoc(&jdoc);
}
dlg->iflags = (unsigned int)VAL_INT(values+22);
if (dlg->state==DLG_STATE_CONFIRMED)
dlg_ka_add(dlg);
if (!dlg->bind_addr[DLG_CALLER_LEG] || !dlg->bind_addr[DLG_CALLEE_LEG]) {
/* non-local socket, probably not our dialog */

@ -77,7 +77,7 @@
#define DLG_IFLAG_TIMER_NORESET (1<<3) /*!< don't reset dialog timers on in-dialog messages reception */
#define DLG_IFLAG_CSEQ_DIFF (1<<4) /*!< CSeq changed in dialog */
#define DLG_IFLAG_PRACK (1<<5) /*!< PRACK was routed during initial state */
#define DLG_IFLAG_DMQ_SYNC (1<<5) /*!< sync this dialog via dmq DMQ*/
#define DLG_IFLAG_DMQ_SYNC (1<<6) /*!< sync this dialog via dmq DMQ*/
#define DLG_CALLER_LEG 0 /*!< attribute that belongs to a caller leg */
#define DLG_CALLEE_LEG 1 /*!< attribute that belongs to a callee leg */

@ -356,6 +356,27 @@ modparam("dialog", "noack_timeout", 90)
</example>
</section>
<section id="dialog.p.end_timeout">
<title><varname>end_timeout</varname> (integer)</title>
<para>
The timeout (in seconds) after which the dialogs in terminated state
are destroyed.
</para>
<para>
<emphasis>
Default value is <quote>300 (5 minutes)</quote>.
</emphasis>
</para>
<example>
<title>Set <varname>end_timeout</varname> parameter</title>
<programlisting format="linespecific">
...
modparam("dialog", "end_timeout", 180)
...
</programlisting>
</example>
</section>
<section id="dialog.p.dlg_extra_hdrs">
<title><varname>dlg_extra_hdrs</varname> (string)</title>
<para>

@ -166,8 +166,8 @@ static int w_ds_is_from_list0(struct sip_msg*, char*, char*);
static int w_ds_is_from_list1(struct sip_msg*, char*, char*);
static int w_ds_is_from_list2(struct sip_msg*, char*, char*);
static int w_ds_is_from_list3(struct sip_msg*, char*, char*, char*);
static int w_ds_list_exist(struct sip_msg*, char*);
static int w_ds_reload(struct sip_msg* msg);
static int w_ds_list_exist(struct sip_msg*, char*, char*);
static int w_ds_reload(struct sip_msg* msg, char*, char*);
static int fixup_ds_is_from_list(void** param, int param_no);
static int fixup_ds_list_exist(void** param,int param_no);
@ -731,7 +731,7 @@ static int w_ds_next_domain(struct sip_msg *msg, char *str1, char *str2)
/**
*
*/
static int w_ds_mark_dst0(struct sip_msg *msg, char *str1, char *str2)
static int ki_ds_mark_dst(sip_msg_t *msg)
{
int state;
@ -745,23 +745,43 @@ static int w_ds_mark_dst0(struct sip_msg *msg, char *str1, char *str2)
/**
*
*/
static int w_ds_mark_dst1(struct sip_msg *msg, char *str1, char *str2)
static int w_ds_mark_dst0(struct sip_msg *msg, char *str1, char *str2)
{
return ki_ds_mark_dst(msg);
}
/**
*
*/
static int ki_ds_mark_dst_state(sip_msg_t *msg, str *sval)
{
int state;
if(str1 == NULL)
return w_ds_mark_dst0(msg, NULL, NULL);
if(sval->s == NULL || sval->len == 0)
return ki_ds_mark_dst(msg);
state = ds_parse_flags(str1, strlen(str1));
state = ds_parse_flags(sval->s, sval->len);
if(state < 0) {
LM_WARN("Failed to parse flag: %s", str1);
LM_WARN("Failed to parse state flags: %.*s", sval->len, sval->s);
return -1;
}
return ds_mark_dst(msg, state);
}
/**
*
*/
static int w_ds_mark_dst1(struct sip_msg *msg, char *str1, char *str2)
{
str sval;
sval.s = str1;
sval.len = strlen(str1);
return ki_ds_mark_dst_state(msg, &sval);
}
/**
*
@ -796,7 +816,7 @@ static int ds_warn_fixup(void **param, int param_no)
return 0;
}
static int w_ds_reload(struct sip_msg *msg)
static int ds_reload(sip_msg_t *msg)
{
if(!ds_db_url.s) {
if(ds_load_list(dslistfile) != 0)
@ -812,11 +832,20 @@ static int w_ds_reload(struct sip_msg *msg)
}
static int w_ds_reload(struct sip_msg *msg, char *str1, char *str2)
{
return ds_reload(msg);
}
static int w_ds_is_from_list0(struct sip_msg *msg, char *str1, char *str2)
{
return ds_is_from_list(msg, -1);
}
static int ki_ds_is_from_lists(sip_msg_t *msg)
{
return ds_is_from_list(msg, -1);
}
static int w_ds_is_from_list1(struct sip_msg *msg, char *set, char *str2)
{
@ -845,6 +874,11 @@ static int w_ds_is_from_list2(struct sip_msg *msg, char *set, char *mode)
return ds_is_addr_from_list(msg, vset, NULL, vmode);
}
static int ki_ds_is_from_list_mode(sip_msg_t *msg, int vset, int vmode)
{
return ds_is_addr_from_list(msg, vset, NULL, vmode);
}
static int w_ds_is_from_list3(
struct sip_msg *msg, char *set, char *mode, char *uri)
{
@ -868,6 +902,10 @@ static int w_ds_is_from_list3(
return ds_is_addr_from_list(msg, vset, &suri, vmode);
}
static int ki_ds_is_from_list_uri(sip_msg_t *msg, int vset, int vmode, str *vuri)
{
return ds_is_addr_from_list(msg, vset, vuri, vmode);
}
static int fixup_ds_is_from_list(void **param, int param_no)
{
@ -879,7 +917,7 @@ static int fixup_ds_is_from_list(void **param, int param_no)
}
/* Check if a given set exist in memory */
static int w_ds_list_exist(struct sip_msg *msg, char *param)
static int w_ds_list_exist(struct sip_msg *msg, char *param, char *p2)
{
int set;
@ -891,6 +929,11 @@ static int w_ds_list_exist(struct sip_msg *msg, char *param)
return ds_list_exist(set);
}
static int ki_ds_list_exists(struct sip_msg *msg, int set)
{
return ds_list_exist(set);
}
static int fixup_ds_list_exist(void **param, int param_no)
{
return fixup_igp_null(param, param_no);
@ -1132,6 +1175,56 @@ static sr_kemi_t sr_kemi_dispatcher_exports[] = {
{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
},
{ str_init("dispatcher"), str_init("ds_mark_dst"),
SR_KEMIP_INT, ki_ds_mark_dst,
{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
},
{ str_init("dispatcher"), str_init("ds_mark_dst_state"),
SR_KEMIP_INT, ki_ds_mark_dst_state,
{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
},
{ str_init("dispatcher"), str_init("ds_is_from_lists"),
SR_KEMIP_INT, ki_ds_is_from_lists,
{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
},
{ str_init("dispatcher"), str_init("ds_is_from_list"),
SR_KEMIP_INT, ds_is_from_list,
{ SR_KEMIP_INT, SR_KEMIP_NONE, SR_KEMIP_NONE,
SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
},
{ str_init("dispatcher"), str_init("ds_is_from_list_mode"),
SR_KEMIP_INT, ki_ds_is_from_list_mode,
{ SR_KEMIP_INT, SR_KEMIP_INT, SR_KEMIP_NONE,
SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
},
{ str_init("dispatcher"), str_init("ds_is_from_list_uri"),
SR_KEMIP_INT, ki_ds_is_from_list_uri,
{ SR_KEMIP_INT, SR_KEMIP_INT, SR_KEMIP_STR,
SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
},
{ str_init("dispatcher"), str_init("ds_load_update"),
SR_KEMIP_INT, ds_load_update,
{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
},
{ str_init("dispatcher"), str_init("ds_load_unset"),
SR_KEMIP_INT, ds_load_unset,
{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
},
{ str_init("dispatcher"), str_init("ds_reload"),
SR_KEMIP_INT, ds_reload,
{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
},
{ str_init("dispatcher"), str_init("ds_list_exists"),
SR_KEMIP_INT, ki_ds_list_exists,
{ SR_KEMIP_INT, SR_KEMIP_NONE, SR_KEMIP_NONE,
SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
},
{ {0, 0}, {0, 0}, 0, NULL, { 0, 0, 0, 0, 0, 0 } }
};
@ -1180,16 +1273,7 @@ static const char *dispatcher_rpc_list_doc[2] = {
*/
int ds_rpc_print_set(ds_set_t *node, rpc_t *rpc, void *ctx, void *rpc_handle)
{
if(!node)
return 0;
int i = 0, rc = 0;
for(; i < 2; ++i) {
rc = ds_rpc_print_set(node->next[i], rpc, ctx, rpc_handle);
if(rc != 0)
return rc;
}
void *rh;
void *sh;
void *vh;
@ -1199,6 +1283,15 @@ int ds_rpc_print_set(ds_set_t *node, rpc_t *rpc, void *ctx, void *rpc_handle)
char c[3];
str data = STR_NULL;
if(!node)
return 0;
for(; i < 2; ++i) {
rc = ds_rpc_print_set(node->next[i], rpc, ctx, rpc_handle);
if(rc != 0)
return rc;
}
if(rpc->struct_add(rpc_handle, "{", "SET", &sh) < 0) {
rpc->fault(ctx, 500, "Internal error set structure");
return -1;

@ -825,7 +825,7 @@
<section>
<title>Parameters</title>
<section>
<section id="drouting.p.db_url">
<title><varname>db_url</varname>(str)</title>
<para>
The database url.
@ -844,7 +844,7 @@ modparam("drouting", "db_url",
</programlisting>
</example>
</section>
<section>
<section id="drouting.p.drd_table">
<title><varname>drd_table</varname>(str)</title>
<para>
The name of the db table storing gateway addresses.
@ -862,7 +862,7 @@ modparam("drouting", "drd_table", "dr_gateways")
</programlisting>
</example>
</section>
<section>
<section id="drouting.p.drr_table">
<title><varname>drr_table</varname>(str)</title>
<para>
The name of the db table storing routing rules.
@ -881,7 +881,7 @@ modparam("drouting", "drr_table", "rules")
</example>
</section>
<section>
<section id="drouting.p.drg_table">
<title><varname>drg_table</varname>(str)</title>
<para>
The name of the db table storing groups.
@ -900,7 +900,7 @@ modparam("drouting", "drg_table", "groups")
</example>
</section>
<section>
<section id="drouting.p.drl_table">
<title><varname>drl_table</varname>(str)</title>
<para>
The name of the db table storing definitions of destination lists (to
@ -924,7 +924,7 @@ modparam("drouting", "drl_table", "my_gw_lists")
</section>
<section>
<title><varname>sort_order</varname> (int)</title>
<title id="drouting.p.sort_order"><varname>sort_order</varname> (int)</title>
<para>
Defines how the destination list should be processed (ordering of
the elements). Possible modes are
@ -982,7 +982,7 @@ modparam("drouting", "sort_order", 2)
</example>
</section>
<section>
<section id="drouting.p.ruri_avp">
<title><varname>ruri_avp</varname> (str)</title>
<para>
The name of the avp for storing Request URIs to be later used
@ -1003,7 +1003,7 @@ modparam("drouting", "ruri_avp", '$avp(i:33)')
</example>
</section>
<section>
<section id="drouting.p.attrs_avp">
<title><varname>attrs_avp</varname> (str)</title>
<para>
The name of the avp for storing the attribute of the current selected
@ -1026,7 +1026,7 @@ modparam("drouting", "atrrs_avp", '$avp(i:67)')
</example>
</section>
<section>
<section id="drouting.p.use_domain">
<title><varname>use_domain</varname> (int)</title>
<para>
Flag to configure whether to use domain match when querying
@ -1102,7 +1102,7 @@ modparam("drouting", "drg_grpid_col", "grpid")
</example>
</section>
<section>
<section id="drouting.p.fetch_rows">
<title><varname>fetch_rows</varname> (int)</title>
<para>
</para>
@ -1122,7 +1122,7 @@ modparam("drouting", "fetch_rows", 1500)
</example>
</section>
<section>
<section id="drouting.p.force_dns">
<title><varname>force_dns</varname> (int)</title>
<para>
Force DNS resolving of GW/destination names (if not IPs) during
@ -1143,7 +1143,7 @@ modparam("drouting", "force_dns", 0)
</example>
</section>
<section>
<section id="drouting.p.enable_keepalive">
<title><varname>enable_keepalive</varname> (int)</title>
<para>
Enable monitoring of GW/destinations using keepalive module.
@ -1168,7 +1168,7 @@ modparam("drouting", "enable_keepalive", 1)
<section>
<title>Functions</title>
<section>
<section id="drouting.f.do_routing">
<title>
<function moreinfo="none">do_routing([groupID])</function>
</title>
@ -1199,7 +1199,7 @@ do_routing("$avp(i:10)");
</example>
</section>
<section>
<section id="drouting.f.next_routing">
<title>
<function moreinfo="none">next_routing()</function>
</title>
@ -1233,7 +1233,7 @@ if (next_routing()) {
</example>
</section>
<section>
<section id="drouting.f.use_next_gw">
<title>
<function moreinfo="none">use_next_gw()</function>
</title>
@ -1279,7 +1279,7 @@ if (goes_to_gw("1")) {
</example>
</section>
<section>
<section id="drouting.f.is_from_gw">
<title>
<function moreinfo="none">is_from_gw([ type, [flag] ])</function>
</title>
@ -1324,7 +1324,7 @@ if (is_from_gw("3","1") {
<section>
<title>RPC Commands</title>
<section>
<section id="drouting.rpc.reload">
<title>
<function moreinfo="none">drouting.reload</function>
</title>

@ -158,7 +158,12 @@ void evrexec_process(evrexec_task_t *it, int idx)
if(it->wait>0) sleep_us(it->wait);
keng = sr_kemi_eng_get();
if(keng==NULL) {
run_top_route(event_rt.rlist[it->rtid], fmsg, 0);
if(it->rtid>=0 && event_rt.rlist[it->rtid]!=NULL) {
run_top_route(event_rt.rlist[it->rtid], fmsg, 0);
} else {
LM_WARN("empty event route block [%.*s]\n",
it->ename.len, it->ename.s);
}
} else {
sidx.s = int2str(idx, &sidx.len);
if(keng->froute(fmsg, EVENT_ROUTE,
@ -227,7 +232,7 @@ int evrexec_param(modparam_t type, void *val)
tmp.ename.s[tmp.ename.len] = '\0';
keng = sr_kemi_eng_get();
if(keng==NULL) {
tmp.rtid = route_lookup(&event_rt, tmp.ename.s);
tmp.rtid = route_get(&event_rt, tmp.ename.s);
if(tmp.rtid == -1) {
LM_ERR("event route not found: %.*s\n", tmp.ename.len, tmp.ename.s);
free_params(params_list);

@ -701,6 +701,30 @@ function ksr_htable_event(evname)
return 1;
end
...
</programlisting>
</example>
</section>
<section id="htable.p.event_callback_mode">
<title><varname>event_callback_mode</varname> (int)</title>
<para>
Control when event_route[htable:init] is executed: 0 - after all
modules were initialized; 1 - in first worker process.
</para>
<para>
Set it to 1 if used in a KEMI script or when needing to use database
(e.g., via sqlops) inside event_route[htable:init].
</para>
<para>
<emphasis>
Default value is 0.
</emphasis>
</para>
<example>
<title>Set <varname>event_callback_mode</varname> parameter</title>
<programlisting format="linespecific">
...
modparam("htable", "event_callback_mode", 1)
...
</programlisting>
</example>
</section>

@ -53,6 +53,7 @@ int ht_timer_interval = 20;
int ht_db_expires_flag = 0;
int ht_enable_dmq = 0;
int ht_timer_procs = 0;
static int ht_event_callback_mode = 0;
str ht_event_callback = STR_NULL;
@ -131,20 +132,21 @@ static cmd_export_t cmds[]={
};
static param_export_t params[]={
{"htable", PARAM_STRING|USE_FUNC_PARAM, (void*)ht_param},
{"db_url", PARAM_STR, &ht_db_url},
{"key_name_column", PARAM_STR, &ht_db_name_column},
{"key_type_column", PARAM_STR, &ht_db_ktype_column},
{"value_type_column", PARAM_STR, &ht_db_vtype_column},
{"key_value_column", PARAM_STR, &ht_db_value_column},
{"expires_column", PARAM_STR, &ht_db_expires_column},
{"array_size_suffix", PARAM_STR, &ht_array_size_suffix},
{"fetch_rows", INT_PARAM, &ht_fetch_rows},
{"timer_interval", INT_PARAM, &ht_timer_interval},
{"db_expires", INT_PARAM, &ht_db_expires_flag},
{"enable_dmq", INT_PARAM, &ht_enable_dmq},
{"timer_procs", PARAM_INT, &ht_timer_procs},
{"event_callback", PARAM_STR, &ht_event_callback},
{"htable", PARAM_STRING|USE_FUNC_PARAM, (void*)ht_param},
{"db_url", PARAM_STR, &ht_db_url},
{"key_name_column", PARAM_STR, &ht_db_name_column},
{"key_type_column", PARAM_STR, &ht_db_ktype_column},
{"value_type_column", PARAM_STR, &ht_db_vtype_column},
{"key_value_column", PARAM_STR, &ht_db_value_column},
{"expires_column", PARAM_STR, &ht_db_expires_column},
{"array_size_suffix", PARAM_STR, &ht_array_size_suffix},
{"fetch_rows", INT_PARAM, &ht_fetch_rows},
{"timer_interval", INT_PARAM, &ht_timer_interval},
{"db_expires", INT_PARAM, &ht_db_expires_flag},
{"enable_dmq", INT_PARAM, &ht_enable_dmq},
{"timer_procs", PARAM_INT, &ht_timer_procs},
{"event_callback", PARAM_STR, &ht_event_callback},
{"event_callback_mode", PARAM_INT, &ht_event_callback_mode},
{0,0,0}
};
@ -219,7 +221,9 @@ static int mod_init(void)
return 0;
}
/**
*
*/
static int child_init(int rank)
{
struct sip_msg *fmsg;
@ -243,9 +247,11 @@ static int child_init(int rank)
}
}
if (rank!=PROC_INIT)
if (ht_event_callback_mode==0 && rank!=PROC_INIT)
return 0;
if (ht_event_callback_mode==1 && rank!=PROC_SIPINIT)
return 0;
rt = -1;
if(ht_event_callback.s==NULL || ht_event_callback.len<=0) {

@ -660,7 +660,7 @@ void send_ccr_interim(struct ro_session* ro_session, unsigned int used, unsigned
LM_DBG("Sending CCR Diameter message.\n");
ro_session->last_event_timestamp_backup = ro_session->last_event_timestamp;
ro_session->last_event_timestamp = get_current_time_micro(); /*this is to make sure that if we get a term request now that we don't double bill for this time we are about to bill for in the interim */
cdpb.AAASessionsUnlock(auth->hash);
if (ro_forced_peer.len > 0) {
@ -760,7 +760,7 @@ static void resume_on_interim_ccr(int is_timeout, void *param, AAAMessage *cca,
goto success;
error:
counter_inc(ims_charging_cnts_h.failed_interim_ccr);
counter_inc(ims_charging_cnts_h.failed_interim_ccr);
if (ro_cca_data)
Ro_free_CCA(ro_cca_data);
@ -985,7 +985,7 @@ static void resume_on_termination_ccr(int is_timeout, void *param, AAAMessage *c
if (!cca) {
LM_ERR("Error in termination CCR.\n");
counter_inc(ims_charging_cnts_h.failed_final_ccrs);
counter_inc(ims_charging_cnts_h.failed_final_ccrs);
return;
}
@ -993,7 +993,7 @@ static void resume_on_termination_ccr(int is_timeout, void *param, AAAMessage *c
if (ro_cca_data == NULL) {
LM_DBG("Could not parse CCA message response.\n");
counter_inc(ims_charging_cnts_h.failed_final_ccrs);
counter_inc(ims_charging_cnts_h.failed_final_ccrs);
return;
}
@ -1012,7 +1012,7 @@ static void resume_on_termination_ccr(int is_timeout, void *param, AAAMessage *c
return;
error:
counter_inc(ims_charging_cnts_h.failed_final_ccrs);
counter_inc(ims_charging_cnts_h.failed_final_ccrs);
Ro_free_CCA(ro_cca_data);
if (!is_timeout && cca) {
cdpb.AAAFreeMessage(&cca);
@ -1071,14 +1071,16 @@ int Ro_Send_CCR(struct sip_msg *msg, struct dlg_cell *dlg, int dir, int reservat
}
//getting asserted identity
if ((asserted_identity = cscf_get_asserted_identity(msg, 0)).len == 0) {
LM_DBG("No P-Asserted-Identity hdr found. Using From hdr for asserted_identity");
asserted_identity = dlg->from_uri;
if (asserted_identity.len > 0 && asserted_identity.s) {
p=(char*)memchr(asserted_identity.s, ';',asserted_identity.len);
if (p)
asserted_identity.len = (p-asserted_identity.s);
}
if (get_custom_user(msg, &asserted_identity) == -1) {
if ((asserted_identity = cscf_get_asserted_identity(msg, 0)).len == 0) {
LM_DBG("No P-Asserted-Identity hdr found. Using From hdr for asserted_identity");
asserted_identity = dlg->from_uri;
if (asserted_identity.len > 0 && asserted_identity.s) {
p=(char*)memchr(asserted_identity.s, ';',asserted_identity.len);
if (p)
asserted_identity.len = (p-asserted_identity.s);
}
}
}
//getting called asserted identity
@ -1251,13 +1253,13 @@ int Ro_Send_CCR(struct sip_msg *msg, struct dlg_cell *dlg, int dir, int reservat
counter_inc(ims_charging_cnts_h.initial_ccrs);
counter_inc(ims_charging_cnts_h.active_ro_sessions);
if (free_called_asserted_identity) shm_free(called_asserted_identity.s); // shm_malloc in cscf_get_public_identity_from_requri
if (free_called_asserted_identity) shm_free(called_asserted_identity.s); // shm_malloc in cscf_get_public_identity_from_requri
return RO_RETURN_BREAK;
error:
LM_DBG("Trying to reserve credit on initial INVITE failed.\n");
if (free_called_asserted_identity) shm_free(called_asserted_identity.s); // shm_malloc in cscf_get_public_identity_from_requri
if (free_called_asserted_identity) shm_free(called_asserted_identity.s); // shm_malloc in cscf_get_public_identity_from_requri
Ro_free_CCR(ro_ccr_data);
if (cc_acc_session) {
cdpb.AAASessionsUnlock(cc_acc_session->hash);
@ -1323,7 +1325,7 @@ static void resume_on_initial_ccr(int is_timeout, void *param, AAAMessage *cca,
create_cca_result_code(0);
goto error0;
}
LM_DBG("Ro result code is [%d]\n", (int)ro_cca_data->resultcode);
create_cca_result_code((int)ro_cca_data->resultcode);
if (ro_cca_data->resultcode != 2001) {
@ -1356,12 +1358,12 @@ static void resume_on_initial_ccr(int is_timeout, void *param, AAAMessage *cca,
}
}
}
/* create the AVPs cca_redirect_uri and cca_fui_action for export to cfg file */
create_cca_fui_avps(fui_action, redirecturi);
/* check result code at mscc level */
if (ro_cca_data->mscc->resultcode != 2001) {
if (ro_cca_data->mscc->resultcode && ro_cca_data->mscc->resultcode != 2001) {
LM_DBG("CCA failure at MSCC level with resultcode [%d]\n", ro_cca_data->mscc->resultcode);
error_code = RO_RETURN_FALSE;
goto error1;
@ -1391,7 +1393,7 @@ static void resume_on_initial_ccr(int is_timeout, void *param, AAAMessage *cca,
LM_DBG("Freeing CCA message\n");
cdpb.AAAFreeMessage(&cca);
link_ro_session(ssd->ro_session, 0);
link_ro_session(ssd->ro_session, 0);
if (ro_db_mode == DB_MODE_REALTIME) {
ssd->ro_session->flags |= RO_SESSION_FLAG_NEW;
@ -1524,7 +1526,7 @@ static int create_cca_fui_avps(int action, str* redirecturi) {
redirecturi_avp_name.s.len = RO_AVP_CCA_FUI_REDIRECT_URI_LENGTH;
char buf[10];
int rc;
action_avp_val.n = action;
action_avp_val.s.len = snprintf(buf, 10, "%i", action);
action_avp_val.s.s = buf;
@ -1535,7 +1537,7 @@ static int create_cca_fui_avps(int action, str* redirecturi) {
LM_ERR("Couldn't create ["RO_AVP_CCA_FUI_ACTION"] AVP\n");
else
LM_DBG("Created AVP ["RO_AVP_CCA_FUI_ACTION"] successfully: value=[%d]\n", action);
if (redirecturi && redirecturi->len >0 && redirecturi->s) {
redirecturi_avp_val.s.len = redirecturi->len;
redirecturi_avp_val.s.s = redirecturi->s;
@ -1547,7 +1549,7 @@ static int create_cca_fui_avps(int action, str* redirecturi) {
else
LM_DBG("Created AVP ["RO_AVP_CCA_FUI_REDIRECT_URI"] successfully: value=[%.*s]\n", redirecturi->len, redirecturi->s);
}
return 1;
}

@ -224,6 +224,8 @@ int isc_match_filter(struct sip_msg *msg, char *str1, udomain_t* d) {
//sometimes s is populated by an ims_getter method cscf_get_terminating_user that alloc memory that must be free-ed at the end
int free_s = 0;
//the callback from the Cx interface in case of unreg terminating initial message is a FAILURE_ROUTE. Hence we need an addl. flag
int firstflag = 0;
int ret = ISC_RETURN_FALSE;
isc_mark new_mark, old_mark;
@ -245,9 +247,10 @@ int isc_match_filter(struct sip_msg *msg, char *str1, udomain_t* d) {
LM_DBG("Message returned s=%d;h=%d;d=%d;a=%.*s\n", old_mark.skip, old_mark.handling, old_mark.direction, old_mark.aor.len, old_mark.aor.s);
} else {
LM_DBG("Starting triggering\n");
firstflag = 1;
}
if (is_route_type(FAILURE_ROUTE)) {
if (is_route_type(FAILURE_ROUTE) && !firstflag) {
/* need to find the handling for the failed trigger */
if (dir == DLG_MOBILE_ORIGINATING) {
k = cscf_get_originating_user(msg, &s);
@ -345,7 +348,7 @@ int isc_match_filter(struct sip_msg *msg, char *str1, udomain_t* d) {
new_mark.skip = m->index + 1;
new_mark.handling = m->default_handling;
new_mark.aor = s;
ret = isc_forward(msg, m, &new_mark);
ret = isc_forward(msg, m, &new_mark, firstflag);
isc_free_match(m);
goto done;
}
@ -383,7 +386,7 @@ int isc_match_filter(struct sip_msg *msg, char *str1, udomain_t* d) {
new_mark.skip = m->index + 1;
new_mark.handling = m->default_handling;
new_mark.aor = s;
ret = isc_forward(msg, m, &new_mark);
ret = isc_forward(msg, m, &new_mark, firstflag);
isc_free_match(m);
goto done;
}

@ -56,7 +56,7 @@
* @param mark - the isc_mark that should be used to mark the message
* @returns #ISC_RETURN_TRUE if OK, #ISC_RETURN_ERROR if not
*/
int isc_forward(struct sip_msg *msg, isc_match *m, isc_mark *mark) {
int isc_forward(struct sip_msg *msg, isc_match *m, isc_mark *mark, int firstflag) {
struct cell *t;
unsigned int hash, label;
ticks_t fr_timeout, fr_inv_timeout;
@ -75,7 +75,7 @@ int isc_forward(struct sip_msg *msg, isc_match *m, isc_mark *mark) {
memcpy(msg->dst_uri.s, m->server_name.s, m->server_name.len);
/* append branch if last trigger failed */
if (is_route_type(FAILURE_ROUTE))
if (is_route_type(FAILURE_ROUTE) && !firstflag)
append_branch(msg, &(msg->first_line.u.request.uri), &(msg->dst_uri), 0, Q_UNSPECIFIED, 0, 0, 0, 0, 0, 0);
// Determines the tm transaction identifiers.

@ -66,7 +66,7 @@ extern int isc_fr_inv_timeout; /**< default ISC INVITE response timeout in ms *
/** SIP Status Code to send to client on Session Termination because AS did not respond */
int isc_forward( struct sip_msg *msg, isc_match *m,isc_mark *mark);
int isc_forward( struct sip_msg *msg, isc_match *m,isc_mark *mark, int firstflag);
#endif

@ -1,301 +1,301 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:simpleType name="tPriority" final="list restriction">
<xs:restriction base="xs:int">
<xs:minInclusive value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tProfilePartIndicator" final="list restriction">
<xs:restriction base="xs:unsignedByte">
<xs:maxInclusive value="1"/>
<xs:enumeration value="0">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">REGISTERED</label>
<definition xml:lang="en">iFC is part of the registered profile</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="1">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">UNREGISTERED</label>
<definition xml:lang="en">iFC is part of the unregistered profile</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tSharedIFCSetID" final="list restriction">
<xs:restriction base="xs:int">
<xs:minInclusive value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tGroupID" final="list restriction">
<xs:restriction base="xs:int">
<xs:minInclusive value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tRegistrationType" final="list restriction">
<xs:restriction base="xs:unsignedByte">
<xs:maxInclusive value="2"/>
<xs:enumeration value="0">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">INITIAL_REGISTRATION</label>
<definition xml:lang="en">Matches to REGISTER messages that are related to initial registration</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="1">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">RE-REGISTRATION</label>
<definition xml:lang="en">Matches to REGISTER messages that are related to re-registration</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="2">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">DE-REGISTRATION</label>
<definition xml:lang="en">Matches to REGISTER messages that are related to de-registration</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tDefaultHandling" final="list restriction">
<xs:restriction base="xs:unsignedByte">
<xs:maxInclusive value="1"/>
<xs:enumeration value="0">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">SESSION_CONTINUED</label>
<definition xml:lang="en">Session Continued</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="1">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">SESSION_TERMINATED</label>
<definition xml:lang="en">Session Terminated</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tDirectionOfRequest" final="list restriction">
<xs:restriction base="xs:unsignedByte">
<xs:maxInclusive value="3"/>
<xs:enumeration value="0">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">ORIGINATING_SESSION</label>
<definition xml:lang="en">Originating Session</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="1">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">TERMINATING_REGISTERED</label>
<definition xml:lang="en">Terminating Session for registered user</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="2">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">TERMINATING_UNREGISTERED</label>
<definition xml:lang="en">Terminating Session for unregistered user</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="3">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">ORIGINATING_UNREGISTERED</label>
<definition xml:lang="en">Originating Session for an unregistered user</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tPrivateID" final="list restriction">
<xs:restriction base="xs:anyURI"/>
</xs:simpleType>
<xs:simpleType name="tSIP_URL" final="list restriction">
<xs:restriction base="xs:anyURI"/>
</xs:simpleType>
<xs:simpleType name="tTEL_URL" final="list restriction">
<xs:restriction base="xs:anyURI"/>
</xs:simpleType>
<xs:simpleType name="tIdentity" final="list restriction">
<xs:union memberTypes="tSIP_URL tTEL_URL"/>
</xs:simpleType>
<xs:simpleType name="tIdentityType" final="list restriction">
<xs:restriction base="xs:unsignedByte">
<xs:minInclusive value="0"/>
<xs:maxInclusive value="2"/>
<xs:enumeration value="0">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">PUBLIC_USER_IDENTITY</label>
<definition xml:lang="en">Identity is a Public User Identity.</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="1">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">DISTINCT_PSI</label>
<definition xml:lang="en">Identity is a distinct Public Service Identity.</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="2">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">WILDCARDED_PSI</label>
<definition xml:lang="en">Identity matches a wildcarded Public Service Identity.</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="tPublicIdentityExtension">
<xs:sequence>
<xs:element name="IdentityType" type="tIdentityType" minOccurs="0"/>
<xs:element name="WildcardedPSI" type="xs:anyURI" minOccurs="0"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:simpleType name="tServiceInfo" final="list restriction">
<xs:restriction base="xs:string">
<xs:minLength value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tString" final="list restriction">
<xs:restriction base="xs:string">
<xs:minLength value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tBool">
<xs:restriction base="xs:boolean"/>
</xs:simpleType>
<xs:simpleType name="tSubscribedMediaProfileId" final="list restriction">
<xs:restriction base="xs:int">
<xs:minInclusive value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="tExtension">
<xs:sequence>
<xs:any processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tServiceProfileExtension">
<xs:sequence>
<xs:element name="SharedIFCSetID" type="tSharedIFCSetID" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tSePoTriExtension">
<xs:sequence>
<xs:element name="RegistrationType" type="tRegistrationType" minOccurs="0" maxOccurs="2"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tIMSSubscription">
<xs:sequence>
<xs:element name="PrivateID" type="tPrivateID"/>
<xs:element name="ServiceProfile" type="tServiceProfile" maxOccurs="unbounded"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tServiceProfile">
<xs:sequence>
<xs:element name="PublicIdentity" type="tPublicIdentity" maxOccurs="unbounded"/>
<xs:element name="CoreNetworkServicesAuthorization" type="tCoreNetworkServicesAuthorization" minOccurs="0"/>
<xs:element name="InitialFilterCriteria" type="tInitialFilterCriteria" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="Extension" type="tServiceProfileExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tCoreNetworkServicesAuthorization">
<xs:sequence>
<xs:element name="SubscribedMediaProfileId" type="tSubscribedMediaProfileId" minOccurs="0"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tInitialFilterCriteria">
<xs:sequence>
<xs:element name="Priority" type="tPriority"/>
<xs:element name="TriggerPoint" type="tTrigger" minOccurs="0"/>
<xs:element name="ApplicationServer" type="tApplicationServer"/>
<xs:element name="ProfilePartIndicator" type="tProfilePartIndicator" minOccurs="0"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tTrigger">
<xs:sequence>
<xs:element name="ConditionTypeCNF" type="tBool"/>
<xs:element name="SPT" type="tSePoTri" maxOccurs="unbounded"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tSePoTri">
<xs:sequence>
<xs:element name="ConditionNegated" type="tBool" default="0" minOccurs="0"/>
<xs:element name="Group" type="tGroupID" maxOccurs="unbounded"/>
<xs:choice>
<xs:element name="RequestURI" type="tString"/>
<xs:element name="Method" type="tString"/>
<xs:element name="SIPHeader" type="tHeader"/>
<xs:element name="SessionCase" type="tDirectionOfRequest"/>
<xs:element name="SessionDescription" type="tSessionDescription"/>
</xs:choice>
<xs:element name="Extension" type="tSePoTriExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tHeader">
<xs:sequence>
<xs:element name="Header" type="tString"/>
<xs:element name="Content" type="tString" minOccurs="0"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tSessionDescription">
<xs:sequence>
<xs:element name="Line" type="tString"/>
<xs:element name="Content" type="tString" minOccurs="0"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tApplicationServer">
<xs:sequence>
<xs:element name="ServerName" type="tSIP_URL"/>
<xs:element name="DefaultHandling" type="tDefaultHandling" minOccurs="0"/>
<xs:element name="ServiceInfo" type="tServiceInfo" minOccurs="0"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tPublicIdentity">
<xs:sequence>
<xs:element name="BarringIndication" type="tBool" default="0" minOccurs="0"/>
<xs:element name="Identity" type="tIdentity"/>
<xs:element name="Extension" type="tPublicIdentityExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:element name="IMSSubscription" type="tIMSSubscription"/>
</xs:schema>
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:simpleType name="tPriority" final="list restriction">
<xs:restriction base="xs:int">
<xs:minInclusive value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tProfilePartIndicator" final="list restriction">
<xs:restriction base="xs:unsignedByte">
<xs:maxInclusive value="1"/>
<xs:enumeration value="0">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">REGISTERED</label>
<definition xml:lang="en">iFC is part of the registered profile</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="1">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">UNREGISTERED</label>
<definition xml:lang="en">iFC is part of the unregistered profile</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tSharedIFCSetID" final="list restriction">
<xs:restriction base="xs:int">
<xs:minInclusive value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tGroupID" final="list restriction">
<xs:restriction base="xs:int">
<xs:minInclusive value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tRegistrationType" final="list restriction">
<xs:restriction base="xs:unsignedByte">
<xs:maxInclusive value="2"/>
<xs:enumeration value="0">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">INITIAL_REGISTRATION</label>
<definition xml:lang="en">Matches to REGISTER messages that are related to initial registration</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="1">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">RE-REGISTRATION</label>
<definition xml:lang="en">Matches to REGISTER messages that are related to re-registration</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="2">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">DE-REGISTRATION</label>
<definition xml:lang="en">Matches to REGISTER messages that are related to de-registration</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tDefaultHandling" final="list restriction">
<xs:restriction base="xs:unsignedByte">
<xs:maxInclusive value="1"/>
<xs:enumeration value="0">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">SESSION_CONTINUED</label>
<definition xml:lang="en">Session Continued</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="1">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">SESSION_TERMINATED</label>
<definition xml:lang="en">Session Terminated</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tDirectionOfRequest" final="list restriction">
<xs:restriction base="xs:unsignedByte">
<xs:maxInclusive value="3"/>
<xs:enumeration value="0">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">ORIGINATING_SESSION</label>
<definition xml:lang="en">Originating Session</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="1">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">TERMINATING_REGISTERED</label>
<definition xml:lang="en">Terminating Session for registered user</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="2">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">TERMINATING_UNREGISTERED</label>
<definition xml:lang="en">Terminating Session for unregistered user</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="3">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">ORIGINATING_UNREGISTERED</label>
<definition xml:lang="en">Originating Session for an unregistered user</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tPrivateID" final="list restriction">
<xs:restriction base="xs:anyURI"/>
</xs:simpleType>
<xs:simpleType name="tSIP_URL" final="list restriction">
<xs:restriction base="xs:anyURI"/>
</xs:simpleType>
<xs:simpleType name="tTEL_URL" final="list restriction">
<xs:restriction base="xs:anyURI"/>
</xs:simpleType>
<xs:simpleType name="tIdentity" final="list restriction">
<xs:union memberTypes="tSIP_URL tTEL_URL"/>
</xs:simpleType>
<xs:simpleType name="tIdentityType" final="list restriction">
<xs:restriction base="xs:unsignedByte">
<xs:minInclusive value="0"/>
<xs:maxInclusive value="2"/>
<xs:enumeration value="0">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">PUBLIC_USER_IDENTITY</label>
<definition xml:lang="en">Identity is a Public User Identity.</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="1">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">DISTINCT_PSI</label>
<definition xml:lang="en">Identity is a distinct Public Service Identity.</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="2">
<xs:annotation>
<xs:documentation>
<label xml:lang="en">WILDCARDED_PSI</label>
<definition xml:lang="en">Identity matches a wildcarded Public Service Identity.</definition>
</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="tPublicIdentityExtension">
<xs:sequence>
<xs:element name="IdentityType" type="tIdentityType" minOccurs="0"/>
<xs:element name="WildcardedPSI" type="xs:anyURI" minOccurs="0"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:simpleType name="tServiceInfo" final="list restriction">
<xs:restriction base="xs:string">
<xs:minLength value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tString" final="list restriction">
<xs:restriction base="xs:string">
<xs:minLength value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="tBool">
<xs:restriction base="xs:boolean"/>
</xs:simpleType>
<xs:simpleType name="tSubscribedMediaProfileId" final="list restriction">
<xs:restriction base="xs:int">
<xs:minInclusive value="0"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="tExtension">
<xs:sequence>
<xs:any processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tServiceProfileExtension">
<xs:sequence>
<xs:element name="SharedIFCSetID" type="tSharedIFCSetID" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tSePoTriExtension">
<xs:sequence>
<xs:element name="RegistrationType" type="tRegistrationType" minOccurs="0" maxOccurs="2"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tIMSSubscription">
<xs:sequence>
<xs:element name="PrivateID" type="tPrivateID"/>
<xs:element name="ServiceProfile" type="tServiceProfile" maxOccurs="unbounded"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tServiceProfile">
<xs:sequence>
<xs:element name="PublicIdentity" type="tPublicIdentity" maxOccurs="unbounded"/>
<xs:element name="CoreNetworkServicesAuthorization" type="tCoreNetworkServicesAuthorization" minOccurs="0"/>
<xs:element name="InitialFilterCriteria" type="tInitialFilterCriteria" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="Extension" type="tServiceProfileExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tCoreNetworkServicesAuthorization">
<xs:sequence>
<xs:element name="SubscribedMediaProfileId" type="tSubscribedMediaProfileId" minOccurs="0"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tInitialFilterCriteria">
<xs:sequence>
<xs:element name="Priority" type="tPriority"/>
<xs:element name="TriggerPoint" type="tTrigger" minOccurs="0"/>
<xs:element name="ApplicationServer" type="tApplicationServer"/>
<xs:element name="ProfilePartIndicator" type="tProfilePartIndicator" minOccurs="0"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tTrigger">
<xs:sequence>
<xs:element name="ConditionTypeCNF" type="tBool"/>
<xs:element name="SPT" type="tSePoTri" maxOccurs="unbounded"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tSePoTri">
<xs:sequence>
<xs:element name="ConditionNegated" type="tBool" default="0" minOccurs="0"/>
<xs:element name="Group" type="tGroupID" maxOccurs="unbounded"/>
<xs:choice>
<xs:element name="RequestURI" type="tString"/>
<xs:element name="Method" type="tString"/>
<xs:element name="SIPHeader" type="tHeader"/>
<xs:element name="SessionCase" type="tDirectionOfRequest"/>
<xs:element name="SessionDescription" type="tSessionDescription"/>
</xs:choice>
<xs:element name="Extension" type="tSePoTriExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tHeader">
<xs:sequence>
<xs:element name="Header" type="tString"/>
<xs:element name="Content" type="tString" minOccurs="0"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tSessionDescription">
<xs:sequence>
<xs:element name="Line" type="tString"/>
<xs:element name="Content" type="tString" minOccurs="0"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tApplicationServer">
<xs:sequence>
<xs:element name="ServerName" type="tSIP_URL"/>
<xs:element name="DefaultHandling" type="tDefaultHandling" minOccurs="0"/>
<xs:element name="ServiceInfo" type="tServiceInfo" minOccurs="0"/>
<xs:element name="Extension" type="tExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tPublicIdentity">
<xs:sequence>
<xs:element name="BarringIndication" type="tBool" default="0" minOccurs="0"/>
<xs:element name="Identity" type="tIdentity"/>
<xs:element name="Extension" type="tPublicIdentityExtension" minOccurs="0"/>
<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:element name="IMSSubscription" type="tIMSSubscription"/>
</xs:schema>

@ -1239,7 +1239,7 @@ int unlink_contact_from_impu(impurecord_t* impu, ucontact_t* contact, int write_
impucontact = impu->linked_contacts.head;
while (impucontact) {
if ((contact = impucontact->contact)) {
if ((contact == impucontact->contact)) {
remove_impucontact_from_list(impu, impucontact);
if (write_to_db && db_mode == WRITE_THROUGH && (db_unlink_contact_from_impu(impu, contact) != 0)) {
LM_ERR("Failed to un-link DB contact [%.*s] from IMPU [%.*s]...continuing but db will be out of sync!\n", contact->c.len, contact->c.s, impu->public_identity.len, impu->public_identity.s);

@ -41,6 +41,7 @@ static ip4_node IPv4ranges[IPv4RANGES_SIZE] = {
{ 0xc0586300, "6TO4-RELAY", 0xffffff00 }, // 192.88.99.0/24
{ 0xc0000200, "TEST-NET", 0xffffff00 }, // 192.0.2/24
{ 0xc0000000, "RESERVED", 0xffffff00 }, // 192.0.0/24
{ 0xc0000000, "6TO4-RELAY", 0xfffffff8 }, // 192.0.0.0/29
{ 0xc0a80000, "PRIVATE", 0xffff0000 }, // 192.168/16
{ 0xa9fe0000, "LINK-LOCAL", 0xffff0000 }, // 169.254/16
{ 0xc6120000, "RESERVED", 0xfffe0000 }, // 198.18/15

@ -25,7 +25,7 @@
#ifndef _IPOPS_DETAILED_IP_TYPE_H
#define _IPOPS_DETAILED_IP_TYPE_H
#define IPv4RANGES_SIZE 16
#define IPv4RANGES_SIZE 17
#define IPv6RANGES_SIZE 29
#include <stdint.h>

@ -390,7 +390,7 @@ int _ip_is_in_subnet_v4(struct in_addr *ip, char *net, size_t netlen,
if (netmask == 32) ipv4_mask = 0xFFFFFFFF;
else ipv4_mask = htonl(~(0xFFFFFFFF >> netmask));
if ((ip->s_addr & ipv4_mask) == net_addr.s_addr)
if ((ip->s_addr & ipv4_mask) == (net_addr.s_addr & ipv4_mask))
return 1;
return 0;
}
@ -415,7 +415,8 @@ int _ip_is_in_subnet_v6(struct in6_addr *ip, char *net, size_t netlen,
else ipv6_mask[i] = 0x00;
}
for (i=0; i<16; i++) ip->s6_addr[i] &= ipv6_mask[i];
if (memcmp(ip->s6_addr, ip->s6_addr, sizeof(net_addr.s6_addr)) == 0)
for (i=0; i<16; i++) net_addr.s6_addr[i] &= ipv6_mask[i];
if (memcmp(ip->s6_addr, net_addr.s6_addr, sizeof(net_addr.s6_addr)) == 0)
return 1;
return 0;
}
@ -1456,4 +1457,4 @@ int mod_register(char *path, int *dlflags, void *p1, void *p2)
{
sr_kemi_modules_add(sr_kemi_ipops_exports);
return 0;
}
}

@ -1,11 +1,11 @@
CC = gcc
FILES = *.c ../netstring.c ../jsonrpc_global.c seatest/seatest.c
OUT_EXE = test
build: $(FILES)
$(CC) -std=gnu99 -pedantic -D TEST -o $(OUT_EXE) $(FILES) -lm -levent
clean:
rm -f *.o core
rebuild: clean build
CC = gcc
FILES = *.c ../netstring.c ../jsonrpc_global.c seatest/seatest.c
OUT_EXE = test
build: $(FILES)
$(CC) -std=gnu99 -pedantic -D TEST -o $(OUT_EXE) $(FILES) -lm -levent
clean:
rm -f *.o core
rebuild: clean build

@ -1,19 +1,19 @@
Copyright (c) 2010 Keith Nicholas
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
Copyright (c) 2010 Keith Nicholas
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

@ -1,248 +1,248 @@
#include "seatest.h"
#include <string.h>
#ifdef WIN32
#include <conio.h>
#include "windows.h"
#else
unsigned int GetTickCount() { return 0;}
void _getch( void ) { }
#endif
static int sea_tests_run = 0;
static int sea_tests_passed = 0;
static int sea_tests_failed = 0;
static char* seatest_current_fixture;
static void (*seatest_suite_setup_func)( void ) = 0;
static void (*seatest_suite_teardown_func)( void ) = 0;
static void (*seatest_fixture_setup)( void ) = 0;
static void (*seatest_fixture_teardown)( void ) = 0;
void suite_setup(void (*setup)( void ))
{
seatest_suite_setup_func = setup;
}
void suite_teardown(void (*teardown)( void ))
{
seatest_suite_teardown_func = teardown;
}
void seatest_suite_setup( void )
{
if(seatest_suite_setup_func != 0) seatest_suite_setup_func();
}
void seatest_suite_teardown( void )
{
if(seatest_suite_teardown_func != 0) seatest_suite_teardown_func();
}
void fixture_setup(void (*setup)( void ))
{
seatest_fixture_setup = setup;
}
void fixture_teardown(void (*teardown)( void ))
{
seatest_fixture_teardown = teardown;
}
void seatest_setup( void )
{
if(seatest_fixture_setup != 0) seatest_fixture_setup();
}
void seatest_teardown( void )
{
if(seatest_fixture_teardown != 0) seatest_fixture_teardown();
}
char* test_file_name(char* path)
{
char* file = path + strlen(path);
while(file != path && *file!= '\\' ) file--;
if(*file == '\\') file++;
return file;
}
static int seatest_fixture_tests_run;
static int seatest_fixture_tests_failed;
void seatest_simple_test_result(int passed, char* reason, const char* function, unsigned int line)
{
if (!passed)
{
printf("%-20s Line %-5d %s\r\n", function, line, reason );
sea_tests_failed++;
}
else
{
sea_tests_passed++;
}
}
void seatest_assert_true(int test, const char* function, unsigned int line)
{
seatest_simple_test_result(test, "Should of been true", function, line);
}
void seatest_assert_false(int test, const char* function, unsigned int line)
{
seatest_simple_test_result(!test, "Should of been false", function, line);
}
void seatest_assert_int_equal(int expected, int actual, const char* function, unsigned int line)
{
char s[SEATEST_PRINT_BUFFER_SIZE];
sprintf(s, "Expected %d but was %d", expected, actual);
seatest_simple_test_result(expected==actual, s, function, line);
}
void seatest_assert_ulong_equal(unsigned long expected, unsigned long actual, const char* function, unsigned int line)
{
char s[SEATEST_PRINT_BUFFER_SIZE];
sprintf(s, "Expected %lu but was %lu", expected, actual);
seatest_simple_test_result(expected==actual, s, function, line);
}
void seatest_assert_float_equal( float expected, float actual, float delta, const char* function, unsigned int line )
{
char s[SEATEST_PRINT_BUFFER_SIZE];
float result = expected-actual;
sprintf(s, "Expected %f but was %f", expected, actual);
if(result < 0.0) result = 0.0f - result;
seatest_simple_test_result( result <= delta, s, function, line);
}
void seatest_assert_double_equal( double expected, double actual, double delta, const char* function, unsigned int line )
{
char s[SEATEST_PRINT_BUFFER_SIZE];
double result = expected-actual;
sprintf(s, "Expected %f but was %f", expected, actual);
if(result < 0.0) result = 0.0 - result;
seatest_simple_test_result( result <= delta, s, function, line);
}
void seatest_assert_string_equal(char* expected, char* actual, const char* function, unsigned int line)
{
char s[SEATEST_PRINT_BUFFER_SIZE];
sprintf(s, "Expected %s but was %s", expected, actual);
seatest_simple_test_result(strcmp(expected, actual)==0, s, function, line);
}
void seatest_assert_string_ends_with(char* expected, char* actual, const char* function, unsigned int line)
{
char s[SEATEST_PRINT_BUFFER_SIZE];
sprintf(s, "Expected %s to end with %s", actual, expected);
seatest_simple_test_result(strcmp(expected, actual+(strlen(actual)-strlen(expected)))==0, s, function, line);
}
void seatest_assert_string_starts_with(char* expected, char* actual, const char* function, unsigned int line)
{
char s[SEATEST_PRINT_BUFFER_SIZE];
sprintf(s, "Expected %s to start with %s", actual, expected);
seatest_simple_test_result(strncmp(expected, actual, strlen(expected))==0, s, function, line);
}
void seatest_assert_string_contains(char* expected, char* actual, const char* function, unsigned int line)
{
char s[SEATEST_PRINT_BUFFER_SIZE];
sprintf(s, "Expected %s to be in %s", expected, actual);
seatest_simple_test_result(strstr(actual, expected)!=0, s, function, line);
}
void seatest_assert_string_doesnt_contain(char* expected, char* actual, const char* function, unsigned int line)
{
char s[SEATEST_PRINT_BUFFER_SIZE];
sprintf(s, "Expected %s not to have %s in it", actual, expected);
seatest_simple_test_result(strstr(actual, expected)==0, s, function, line);
}
void seatest_run_test(void)
{
sea_tests_run++;
}
void seatest_header_printer(char* s, int length, char f)
{
int l = strlen(s);
int d = (length- (l + 2)) / 2;
int i;
for(i = 0; i<d; i++) printf("%c",f);
printf(" %s ", s);
for(i = (d+l+2); i<length; i++) printf("%c",f);
printf("\r\n");
}
void seatest_test_fixture_start(char* filepath)
{
seatest_current_fixture = test_file_name(filepath);
seatest_header_printer(seatest_current_fixture, 50, '-');
seatest_fixture_tests_failed = sea_tests_failed;
seatest_fixture_tests_run = sea_tests_run;
seatest_fixture_teardown = 0;
seatest_fixture_setup = 0;
}
void seatest_test_fixture_end()
{
char s[SEATEST_PRINT_BUFFER_SIZE];
sprintf(s, "%d run %d failed", sea_tests_run-seatest_fixture_tests_run, sea_tests_failed-seatest_fixture_tests_failed);
seatest_header_printer(s, 50, ' ');
printf("\r\n");
}
static char* seatest_fixture_filter = 0;
static char* seatest_test_filter = 0;
void fixture_filter(char* filter)
{
seatest_fixture_filter = filter;
}
void test_filter(char* filter)
{
seatest_test_filter = filter;
}
int seatest_should_run( char* fixture, char* test)
{
int run = 1;
if(seatest_fixture_filter)
{
if(strncmp(seatest_fixture_filter, fixture, strlen(seatest_fixture_filter)) != 0) run = 0;
}
if(seatest_test_filter)
{
if(strncmp(seatest_test_filter, test, strlen(seatest_test_filter)) != 0) run = 0;
}
return run;
}
int run_tests(void (*tests)(void))
{
unsigned long end;
unsigned long start = GetTickCount();
tests();
end = GetTickCount();
printf("\r\n\r\n==================SEATEST v%s====================\r\n\r\n", SEATEST_VERSION);
if (sea_tests_failed > 0) {
printf(" Failed\r\n");
}
else {
printf(" ALL TESTS PASSED\r\n");
}
printf(" %d tests run\r\n", sea_tests_run);
printf(" in %lu ms\r\n",end - start);
printf("==================================================\r\n");
_getch();
return sea_tests_failed == 0;
}
#include "seatest.h"
#include <string.h>
#ifdef WIN32
#include <conio.h>
#include "windows.h"
#else
unsigned int GetTickCount() { return 0;}
void _getch( void ) { }
#endif
static int sea_tests_run = 0;
static int sea_tests_passed = 0;
static int sea_tests_failed = 0;
static char* seatest_current_fixture;
static void (*seatest_suite_setup_func)( void ) = 0;
static void (*seatest_suite_teardown_func)( void ) = 0;
static void (*seatest_fixture_setup)( void ) = 0;
static void (*seatest_fixture_teardown)( void ) = 0;
void suite_setup(void (*setup)( void ))
{
seatest_suite_setup_func = setup;
}
void suite_teardown(void (*teardown)( void ))
{
seatest_suite_teardown_func = teardown;
}
void seatest_suite_setup( void )
{
if(seatest_suite_setup_func != 0) seatest_suite_setup_func();
}
void seatest_suite_teardown( void )
{
if(seatest_suite_teardown_func != 0) seatest_suite_teardown_func();
}
void fixture_setup(void (*setup)( void ))
{
seatest_fixture_setup = setup;
}
void fixture_teardown(void (*teardown)( void ))
{
seatest_fixture_teardown = teardown;
}
void seatest_setup( void )
{
if(seatest_fixture_setup != 0) seatest_fixture_setup();
}
void seatest_teardown( void )
{
if(seatest_fixture_teardown != 0) seatest_fixture_teardown();
}
char* test_file_name(char* path)
{
char* file = path + strlen(path);
while(file != path && *file!= '\\' ) file--;
if(*file == '\\') file++;
return file;
}
static int seatest_fixture_tests_run;
static int seatest_fixture_tests_failed;
void seatest_simple_test_result(int passed, char* reason, const char* function, unsigned int line)
{
if (!passed)
{
printf("%-20s Line %-5d %s\r\n", function, line, reason );
sea_tests_failed++;
}
else
{
sea_tests_passed++;
}
}
void seatest_assert_true(int test, const char* function, unsigned int line)
{
seatest_simple_test_result(test, "Should of been true", function, line);
}
void seatest_assert_false(int test, const char* function, unsigned int line)
{
seatest_simple_test_result(!test, "Should of been false", function, line);
}
void seatest_assert_int_equal(int expected, int actual, const char* function, unsigned int line)
{
char s[SEATEST_PRINT_BUFFER_SIZE];
sprintf(s, "Expected %d but was %d", expected, actual);
seatest_simple_test_result(expected==actual, s, function, line);
}
void seatest_assert_ulong_equal(unsigned long expected, unsigned long actual, const char* function, unsigned int line)
{
char s[SEATEST_PRINT_BUFFER_SIZE];
sprintf(s, "Expected %lu but was %lu", expected, actual);
seatest_simple_test_result(expected==actual, s, function, line);
}
void seatest_assert_float_equal( float expected, float actual, float delta, const char* function, unsigned int line )
{
char s[SEATEST_PRINT_BUFFER_SIZE];
float result = expected-actual;
sprintf(s, "Expected %f but was %f", expected, actual);
if(result < 0.0) result = 0.0f - result;
seatest_simple_test_result( result <= delta, s, function, line);
}
void seatest_assert_double_equal( double expected, double actual, double delta, const char* function, unsigned int line )
{
char s[SEATEST_PRINT_BUFFER_SIZE];
double result = expected-actual;
sprintf(s, "Expected %f but was %f", expected, actual);
if(result < 0.0) result = 0.0 - result;
seatest_simple_test_result( result <= delta, s, function, line);
}
void seatest_assert_string_equal(char* expected, char* actual, const char* function, unsigned int line)
{
char s[SEATEST_PRINT_BUFFER_SIZE];
sprintf(s, "Expected %s but was %s", expected, actual);
seatest_simple_test_result(strcmp(expected, actual)==0, s, function, line);
}
void seatest_assert_string_ends_with(char* expected, char* actual, const char* function, unsigned int line)
{
char s[SEATEST_PRINT_BUFFER_SIZE];
sprintf(s, "Expected %s to end with %s", actual, expected);
seatest_simple_test_result(strcmp(expected, actual+(strlen(actual)-strlen(expected)))==0, s, function, line);
}
void seatest_assert_string_starts_with(char* expected, char* actual, const char* function, unsigned int line)
{
char s[SEATEST_PRINT_BUFFER_SIZE];
sprintf(s, "Expected %s to start with %s", actual, expected);
seatest_simple_test_result(strncmp(expected, actual, strlen(expected))==0, s, function, line);
}
void seatest_assert_string_contains(char* expected, char* actual, const char* function, unsigned int line)
{
char s[SEATEST_PRINT_BUFFER_SIZE];
sprintf(s, "Expected %s to be in %s", expected, actual);
seatest_simple_test_result(strstr(actual, expected)!=0, s, function, line);
}
void seatest_assert_string_doesnt_contain(char* expected, char* actual, const char* function, unsigned int line)
{
char s[SEATEST_PRINT_BUFFER_SIZE];
sprintf(s, "Expected %s not to have %s in it", actual, expected);
seatest_simple_test_result(strstr(actual, expected)==0, s, function, line);
}
void seatest_run_test(void)
{
sea_tests_run++;
}
void seatest_header_printer(char* s, int length, char f)
{
int l = strlen(s);
int d = (length- (l + 2)) / 2;
int i;
for(i = 0; i<d; i++) printf("%c",f);
printf(" %s ", s);
for(i = (d+l+2); i<length; i++) printf("%c",f);
printf("\r\n");
}
void seatest_test_fixture_start(char* filepath)
{
seatest_current_fixture = test_file_name(filepath);
seatest_header_printer(seatest_current_fixture, 50, '-');
seatest_fixture_tests_failed = sea_tests_failed;
seatest_fixture_tests_run = sea_tests_run;
seatest_fixture_teardown = 0;
seatest_fixture_setup = 0;
}
void seatest_test_fixture_end()
{
char s[SEATEST_PRINT_BUFFER_SIZE];
sprintf(s, "%d run %d failed", sea_tests_run-seatest_fixture_tests_run, sea_tests_failed-seatest_fixture_tests_failed);
seatest_header_printer(s, 50, ' ');
printf("\r\n");
}
static char* seatest_fixture_filter = 0;
static char* seatest_test_filter = 0;
void fixture_filter(char* filter)
{
seatest_fixture_filter = filter;
}
void test_filter(char* filter)
{
seatest_test_filter = filter;
}
int seatest_should_run( char* fixture, char* test)
{
int run = 1;
if(seatest_fixture_filter)
{
if(strncmp(seatest_fixture_filter, fixture, strlen(seatest_fixture_filter)) != 0) run = 0;
}
if(seatest_test_filter)
{
if(strncmp(seatest_test_filter, test, strlen(seatest_test_filter)) != 0) run = 0;
}
return run;
}
int run_tests(void (*tests)(void))
{
unsigned long end;
unsigned long start = GetTickCount();
tests();
end = GetTickCount();
printf("\r\n\r\n==================SEATEST v%s====================\r\n\r\n", SEATEST_VERSION);
if (sea_tests_failed > 0) {
printf(" Failed\r\n");
}
else {
printf(" ALL TESTS PASSED\r\n");
}
printf(" %d tests run\r\n", sea_tests_run);
printf(" in %lu ms\r\n",end - start);
printf("==================================================\r\n");
_getch();
return sea_tests_failed == 0;
}

@ -1,74 +1,74 @@
#ifndef SEATEST_H
#define SEATEST_H
#include <stdio.h>
/*
Defines
*/
#define SEATEST_VERSION "0.5"
#define SEATEST_PROJECT_HOME "http://code.google.com/p/seatest/"
#define SEATEST_PRINT_BUFFER_SIZE 100000
/*
Declarations
*/
void seatest_test_fixture_start(char* filepath);
void seatest_test_fixture_end( void );
void seatest_simple_test_result(int passed, char* reason, const char* function, unsigned int line);
void seatest_assert_true(int test, const char* function, unsigned int line);
void seatest_assert_false(int test, const char* function, unsigned int line);
void seatest_assert_int_equal(int expected, int actual, const char* function, unsigned int line);
void seatest_assert_ulong_equal(unsigned long expected, unsigned long actual, const char* function, unsigned int line);
void seatest_assert_float_equal(float expected, float actual, float delta, const char* function, unsigned int line);
void seatest_assert_double_equal(double expected, double actual, double delta, const char* function, unsigned int line);
void seatest_assert_string_equal(char* expected, char* actual, const char* function, unsigned int line);
void seatest_assert_string_ends_with(char* expected, char* actual, const char* function, unsigned int line);
void seatest_assert_string_starts_with(char* expected, char* actual, const char* function, unsigned int line);
void seatest_assert_string_contains(char* expected, char* actual, const char* function, unsigned int line);
void seatest_assert_string_doesnt_contain(char* expected, char* actual, const char* function, unsigned int line);
int seatest_should_run( char* fixture, char* test);
void seatest_run_test(void);
void seatest_setup( void );
void seatest_teardown( void );
void seatest_suite_teardown( void );
void seatest_suite_setup( void );
/*
Assert Macros
*/
#define assert_true(test) do { seatest_assert_true(test, __FUNCTION__, __LINE__); } while (0)
#define assert_false(test) do { seatest_assert_false(test, __FUNCTION__, __LINE__); } while (0)
#define assert_int_equal(expected, actual) do { seatest_assert_int_equal(expected, actual, __FUNCTION__, __LINE__); } while (0)
#define assert_ulong_equal(expected, actual) do { seatest_assert_ulong_equal(expected, actual, __FUNCTION__, __LINE__); } while (0)
#define assert_string_equal(expected, actual) do { seatest_assert_string_equal(expected, actual, __FUNCTION__, __LINE__); } while (0)
#define assert_n_array_equal(expected, actual, n) do { int seatest_count; for(seatest_count=0; seatest_count<n; seatest_count++) { char s_seatest[SEATEST_PRINT_BUFFER_SIZE]; sprintf(s_seatest,"Expected %d to be %d at position %d", actual[seatest_count], expected[seatest_count], seatest_count); seatest_simple_test_result((expected[seatest_count] == actual[seatest_count]), s_seatest, __FUNCTION__, __LINE__);} } while (0)
#define assert_bit_set(bit_number, value) { seatest_simple_test_result(((1 << bit_number) & value), " Expected bit to be set" , __FUNCTION__, __LINE__); } while (0)
#define assert_bit_not_set(bit_number, value) { seatest_simple_test_result(!((1 << bit_number) & value), " Expected bit not to to be set" , __FUNCTION__, __LINE__); } while (0)
#define assert_bit_mask_matches(value, mask) { seatest_simple_test_result(((value & mask) == mask), " Expected all bits of mask to be set" , __FUNCTION__, __LINE__); } while (0)
#define assert_fail(message) { seatest_simple_test_result(0, message, __FUNCTION__, __LINE__); } while (0)
#define assert_float_equal(expected, actual, delta) do { seatest_assert_float_equal(expected, actual, delta, __FUNCTION__, __LINE__); } while (0)
#define assert_double_equal(expected, actual, delta) do { seatest_assert_double_equal(expected, actual, delta, __FUNCTION__, __LINE__); } while (0)
#define assert_string_contains(expected, actual) do { seatest_assert_string_contains(expected, actual, __FUNCTION__, __LINE__); } while (0)
#define assert_string_doesnt_contain(expected, actual) do { seatest_assert_string_doesnt_contain(expected, actual, __FUNCTION__, __LINE__); } while (0)
#define assert_string_starts_with(expected, actual) do { seatest_assert_string_starts_with(expected, actual, __FUNCTION__, __LINE__); } while (0)
#define assert_string_ends_with(expected, actual) do { seatest_assert_string_ends_with(expected, actual, __FUNCTION__, __LINE__); } while (0)
/*
Fixture / Test Management
*/
void fixture_setup(void (*setup)( void ));
void fixture_teardown(void (*teardown)( void ));
#define run_test(test) do { if(seatest_should_run(__FILE__, #test)) {seatest_suite_setup(); seatest_setup(); test(); seatest_teardown(); seatest_suite_teardown(); seatest_run_test(); }} while (0)
#define test_fixture_start() do { seatest_test_fixture_start(__FILE__); } while (0)
#define test_fixture_end() do { seatest_test_fixture_end();} while (0)
void fixture_filter(char* filter);
void test_filter(char* filter);
int run_tests(void (*tests)(void));
void suite_teardown(void (*teardown)( void ));
void suite_setup(void (*setup)( void ));
#endif
#ifndef SEATEST_H
#define SEATEST_H
#include <stdio.h>
/*
Defines
*/
#define SEATEST_VERSION "0.5"
#define SEATEST_PROJECT_HOME "http://code.google.com/p/seatest/"
#define SEATEST_PRINT_BUFFER_SIZE 100000
/*
Declarations
*/
void seatest_test_fixture_start(char* filepath);
void seatest_test_fixture_end( void );
void seatest_simple_test_result(int passed, char* reason, const char* function, unsigned int line);
void seatest_assert_true(int test, const char* function, unsigned int line);
void seatest_assert_false(int test, const char* function, unsigned int line);
void seatest_assert_int_equal(int expected, int actual, const char* function, unsigned int line);
void seatest_assert_ulong_equal(unsigned long expected, unsigned long actual, const char* function, unsigned int line);
void seatest_assert_float_equal(float expected, float actual, float delta, const char* function, unsigned int line);
void seatest_assert_double_equal(double expected, double actual, double delta, const char* function, unsigned int line);
void seatest_assert_string_equal(char* expected, char* actual, const char* function, unsigned int line);
void seatest_assert_string_ends_with(char* expected, char* actual, const char* function, unsigned int line);
void seatest_assert_string_starts_with(char* expected, char* actual, const char* function, unsigned int line);
void seatest_assert_string_contains(char* expected, char* actual, const char* function, unsigned int line);
void seatest_assert_string_doesnt_contain(char* expected, char* actual, const char* function, unsigned int line);
int seatest_should_run( char* fixture, char* test);
void seatest_run_test(void);
void seatest_setup( void );
void seatest_teardown( void );
void seatest_suite_teardown( void );
void seatest_suite_setup( void );
/*
Assert Macros
*/
#define assert_true(test) do { seatest_assert_true(test, __FUNCTION__, __LINE__); } while (0)
#define assert_false(test) do { seatest_assert_false(test, __FUNCTION__, __LINE__); } while (0)
#define assert_int_equal(expected, actual) do { seatest_assert_int_equal(expected, actual, __FUNCTION__, __LINE__); } while (0)
#define assert_ulong_equal(expected, actual) do { seatest_assert_ulong_equal(expected, actual, __FUNCTION__, __LINE__); } while (0)
#define assert_string_equal(expected, actual) do { seatest_assert_string_equal(expected, actual, __FUNCTION__, __LINE__); } while (0)
#define assert_n_array_equal(expected, actual, n) do { int seatest_count; for(seatest_count=0; seatest_count<n; seatest_count++) { char s_seatest[SEATEST_PRINT_BUFFER_SIZE]; sprintf(s_seatest,"Expected %d to be %d at position %d", actual[seatest_count], expected[seatest_count], seatest_count); seatest_simple_test_result((expected[seatest_count] == actual[seatest_count]), s_seatest, __FUNCTION__, __LINE__);} } while (0)
#define assert_bit_set(bit_number, value) { seatest_simple_test_result(((1 << bit_number) & value), " Expected bit to be set" , __FUNCTION__, __LINE__); } while (0)
#define assert_bit_not_set(bit_number, value) { seatest_simple_test_result(!((1 << bit_number) & value), " Expected bit not to to be set" , __FUNCTION__, __LINE__); } while (0)
#define assert_bit_mask_matches(value, mask) { seatest_simple_test_result(((value & mask) == mask), " Expected all bits of mask to be set" , __FUNCTION__, __LINE__); } while (0)
#define assert_fail(message) { seatest_simple_test_result(0, message, __FUNCTION__, __LINE__); } while (0)
#define assert_float_equal(expected, actual, delta) do { seatest_assert_float_equal(expected, actual, delta, __FUNCTION__, __LINE__); } while (0)
#define assert_double_equal(expected, actual, delta) do { seatest_assert_double_equal(expected, actual, delta, __FUNCTION__, __LINE__); } while (0)
#define assert_string_contains(expected, actual) do { seatest_assert_string_contains(expected, actual, __FUNCTION__, __LINE__); } while (0)
#define assert_string_doesnt_contain(expected, actual) do { seatest_assert_string_doesnt_contain(expected, actual, __FUNCTION__, __LINE__); } while (0)
#define assert_string_starts_with(expected, actual) do { seatest_assert_string_starts_with(expected, actual, __FUNCTION__, __LINE__); } while (0)
#define assert_string_ends_with(expected, actual) do { seatest_assert_string_ends_with(expected, actual, __FUNCTION__, __LINE__); } while (0)
/*
Fixture / Test Management
*/
void fixture_setup(void (*setup)( void ));
void fixture_teardown(void (*teardown)( void ));
#define run_test(test) do { if(seatest_should_run(__FILE__, #test)) {seatest_suite_setup(); seatest_setup(); test(); seatest_teardown(); seatest_suite_teardown(); seatest_run_test(); }} while (0)
#define test_fixture_start() do { seatest_test_fixture_start(__FILE__); } while (0)
#define test_fixture_end() do { seatest_test_fixture_end();} while (0)
void fixture_filter(char* filter);
void test_filter(char* filter);
int run_tests(void (*tests)(void));
void suite_teardown(void (*teardown)( void ));
void suite_setup(void (*setup)( void ));
#endif

@ -459,6 +459,7 @@ event_route[xhttp:request] {
<programlisting format="linespecific">
...
jsonrpc_exec('{"jsonrpc": "2.0", "method": "dispatcher.reload", "id": 1}');
xlog("jsonrpc response code: $jsonrpl(code) - the body is: $jsonrpl(body)\n");
...
</programlisting>
</example>

@ -63,26 +63,11 @@ static const char *keepalive_rpc_list_doc[2] = {
static void keepalive_rpc_list(rpc_t *rpc, void *ctx)
{
void *foo, *bar, *baz;
void *sub;
ka_dest_t *dest;
char *_ctime;
char *_utime;
char *_dtime;
str text = str_init("foobar");
if(rpc->add(ctx, "Sd", &text, 42) < 0)
LM_ERR("failed creating RPC struct\n");
if(rpc->add(ctx, "Sd", &text, 42) < 0)
LM_ERR("failed creating RPC struct\n");
rpc->add(ctx, "{", &foo);
rpc->struct_add(foo, "Sd", "text", &text, "number", 42);
rpc->add(ctx, "{", &bar);
rpc->struct_add(bar, "[", "list", &baz);
rpc->struct_add(baz, "d", "nn", 17);
rpc->struct_add(baz, "d", "nn", 22);
for(dest = ka_destinations_list->first; dest != NULL; dest = dest->next) {
rpc->add(ctx, "{", &sub);

@ -170,7 +170,7 @@
<section>
<title>Parameters</title>
<section>
<section id="lcr.p.db_url">
<title><varname>db_url</varname> (string)</title>
<para>
&url; of the database table to be used.
@ -191,7 +191,7 @@ modparam("lcr","db_url","&exampledb;")
</example>
</section>
<section>
<section id="lcr.p.lcr_gw_table">
<title><varname>lcr_gw_table</varname> (string)</title>
<para>
Name of the table holding gateways definitions.
@ -496,7 +496,7 @@ modparam("lcr", "defunct_column", "defunct_until")
</example>
</section>
<section>
<section id="lcr.p.lcr_rule_table">
<title><varname>lcr_rule_table</varname> (string)</title>
<para>
Name of the table holding the LCR rules.
@ -644,7 +644,7 @@ modparam("lcr", "enabled_column", "in_use")
</example>
</section>
<section>
<section id="lcr.p.lcr_rule_target_table">
<title><varname>lcr_rule_target_table</varname> (string)</title>
<para>
Name of the table holding information about the LCR rule
@ -755,7 +755,7 @@ modparam("lcr","weight_column", "target_weight")
</example>
</section>
<section>
<section id="lcr.p.lcr_count">
<title><varname>lcr_count</varname> (integer)</title>
<para>
Maximun value of lcr_id.
@ -778,7 +778,7 @@ modparam("lcr", "lcr_count", 10)
</example>
</section>
<section>
<section id="lcr.p.gw_uri_avp">
<title><varname>gw_uri_avp</varname> (AVP string)</title>
<para>
Internal AVP that load_gws() function uses to store
@ -801,7 +801,7 @@ modparam("lcr", "gw_uri_avp", "$avp(i:709)")
</example>
</section>
<section>
<section id="lcr.p.ruri_user_avp">
<title><varname>ruri_user_avp</varname> (AVP string)</title>
<para>
Internal AVP that next_gw function uses to store
@ -823,7 +823,7 @@ modparam("lcr", "ruri_user_avp", "$avp(i:500)")
</example>
</section>
<section>
<section id="lcr.p.tag_avp">
<title><varname>tag_avp</varname> (AVP string)</title>
<para>
If defined, an AVP where successful next_gw and from_gw
@ -845,7 +845,7 @@ modparam("lcr", "tag_avp", "$avp(lcr_tag)")
</example>
</section>
<section>
<section id="lcr.p.flags_avp">
<title><varname>flags_avp</varname> (AVP string)</title>
<para>
If defined, an AVP where successful next_gw and from_gw
@ -867,7 +867,7 @@ modparam("lcr", "flags_avp", "$avp(i:712)")
</example>
</section>
<section>
<section id="lcr.p.mt_pv_values">
<title><varname>mt_pv_values</varname> (AVP string)</title>
<para>
If defined and mt_value is given for a rule, load_gws() matches
@ -892,7 +892,7 @@ modparam("lcr", "mt_pv_values", "$avp(mt_values)")
</example>
</section>
<section>
<section id="lcr.p.mtree">
<title><varname>mtree</varname> (string)</title>
<para>
Name of mtree to which load_gws() matches caller URI userpart.
@ -912,7 +912,7 @@ modparam("lcr", "mtree", "caller_tree")
</example>
</section>
<section>
<section id="lcr.p.defunct_capability">
<title><varname>defunct_capability</varname> (integer)</title>
<para>
Tells if defunct capability of (non-responsive) gateways is
@ -936,7 +936,7 @@ modparam("lcr", "defunct_capability", 1)
</example>
</section>
<section>
<section id="lcr.p.lcr_id_avp">
<title><varname>lcr_id_avp</varname> (AVP string)</title>
<para>
Internal AVP that load_gws() function uses to store
@ -959,7 +959,7 @@ modparam("lcr", "lcr_id_avp", "$avp(s:lcr_id_avp)")
</example>
</section>
<section>
<section id="lcr.p.defunct_gw_avp">
<title><varname>defunct_gw_avp</varname> (AVP string)</title>
<para>
Internal AVP that next_gw() function uses to store
@ -984,7 +984,7 @@ modparam("lcr", "defunct_gw_avp", "$avp(s:defunct_gw_avp)")
</example>
</section>
<section>
<section id="lcr.p.lcr_rule_hash_size">
<title><varname>lcr_rule_hash_size</varname> (integer)</title>
<para>
Defines the size of hash table used to store LCR rules.
@ -1010,7 +1010,7 @@ modparam("lcr", "lcr_rule_hash_size", 1024)
</example>
</section>
<section>
<section id="lcr.p.lcr_gw_count">
<title><varname>lcr_gw_count</varname> (integer)</title>
<para>
Defines the maximum number of gateways in lcr_gw table.
@ -1032,7 +1032,7 @@ modparam("lcr", "lcr_gw_count", 1024)
</example>
</section>
<section>
<section id="lcr.p.dont_strip_or_prefix_flag">
<title><varname>dont_strip_or_prefix_flag</varname> (integer)</title>
<para>
Defines the flag number used to tell if stripping and
@ -1057,7 +1057,7 @@ modparam("lcr", "dont_strip_or_prefix_flag", 10)
</example>
</section>
<section>
<section id="lcr.p.priority_ordering">
<title><varname>priority_ordering</varname> (integer)</title>
<para>
Defines how matching gateways are ordered (see Overview section).
@ -1080,7 +1080,7 @@ modparam("lcr", "priority_ordering", 1)
</example>
</section>
<section>
<section id="lcr.p.fetch_rows">
<title><varname>fetch_rows</varname> (integer)</title>
<para>
The number of the rows to be fetched at once from database
@ -1106,7 +1106,7 @@ modparam("lcr", "fetch_rows", 3000)
</example>
</section>
<section>
<section id="lcr.p.ping_interval">
<title><varname>ping_interval</varname> (integer)</title>
<para>
Interval in seconds for sending OPTIONS ping requests
@ -1141,7 +1141,7 @@ modparam("lcr", "ping_interval", 15)
</example>
</section>
<section>
<section id="lcr.p.ping_inactivate_threshold">
<title><varname>ping_inactivate_threshold</varname> (integer)</title>
<para>
Tells after how many failures (= inactivate_gw() function
@ -1165,7 +1165,7 @@ modparam("lcr", "ping_inactivate_threshold", 3)
</example>
</section>
<section>
<section id="lcr.p.ping_valid_reply_codes">
<title><varname>ping_valid_reply_codes</varname> (string)</title>
<para>
A comma separated list of SIP reply codes, which are
@ -1191,7 +1191,7 @@ modparam("lcr", "ping_valid_reply_codes", "403,405,501")
</example>
</section>
<section>
<section id="lcr.p.ping_from">
<title><varname>ping_from</varname> (string)</title>
<para>
From URI used in OPTIONS ping requests.
@ -1213,7 +1213,7 @@ modparam("lcr", "ping_from", "sip:proxy.operator.com")
</example>
</section>
<section>
<section id="lcr.p.ping_socket">
<title><varname>ping_socket</varname> (string)</title>
<para>
Socket to be used for sending OPTIONS ping request. If not
@ -1240,7 +1240,7 @@ modparam("lcr", "ping_socket", "192.98.102.10:5060")
<section>
<title>Functions</title>
<section>
<section id="lcr.f.load_gws">
<title>
<function moreinfo="none">load_gws(lcr_id[, uri_user[, caller_uri]])
</function>
@ -1283,7 +1283,7 @@ if (!load_gws(1, $rU, $var(caller_uri))) {
</example>
</section>
<section>
<section id="lcr.f.next_gw">
<title>
<function moreinfo="none">next_gw()</function>
</title>
@ -1340,7 +1340,7 @@ if (!next_gw()) {
</example>
</section>
<section>
<section id="lcr.f.inactivate_gw">
<title>
<function moreinfo="none">inactivate_gw()</function>
</title>
@ -1372,7 +1372,7 @@ failure_route [GW_FAILURE] {
</example>
</section>
<section>
<section id="lcr.f.defunct_gw">
<title>
<function moreinfo="none">defunct_gw(period)</function>
</title>
@ -1400,7 +1400,7 @@ defunct_gw(60);
</example>
</section>
<section>
<section id="lcr.f.from_gw">
<title>
<function moreinfo="none">from_gw(lcr_id[, ip_addr, proto])</function>
</title>
@ -1450,7 +1450,7 @@ if (from_gw(1, $avp(s:real_source_addr), 2) {
</example>
</section>
<section>
<section id="lcr.f.from_any_gw">
<title>
<function moreinfo="none">from_any_gw([ip_addr, proto])</function>
</title>
@ -1496,7 +1496,7 @@ $var(lcr_id) = from_any_gw("192.168.1.1", 3);
</example>
</section>
<section>
<section id="lcr.f.to_gw">
<title>
<function moreinfo="none">to_gw(lcr_id[, ip_addr, proto])</function>
</title>
@ -1533,7 +1533,7 @@ if (to_gw("1")) {
</example>
</section>
<section>
<section id="lcr.f.to_any_gw">
<title>
<function moreinfo="none">to_any_gw([ip_addr, proto])</function>
</title>
@ -1577,7 +1577,7 @@ if (to_any_gw("192.55.66.2", 1)) {
<section>
<title>RPC Commands</title>
<section>
<section id="lcr.rpc.reload">
<title><function>lcr.reload</function></title>
<para>
Causes lcr module to re-read the contents of
@ -1595,7 +1595,7 @@ if (to_any_gw("192.55.66.2", 1)) {
</example>
</section>
<section>
<section id="lcr.rpc.dump_gws">
<title><function>lcr.dump_gws</function></title>
<para>
Causes lcr module to dump the contents of its
@ -1610,7 +1610,7 @@ if (to_any_gw("192.55.66.2", 1)) {
</example>
</section>
<section>
<section id="lcr.rpc.dump_rules">
<title><function>lcr.dump_rules</function></title>
<para>
Causes lcr module to dump the contents of its
@ -1625,7 +1625,7 @@ if (to_any_gw("192.55.66.2", 1)) {
</example>
</section>
<section>
<section id="lcr.rpc.load_gws">
<title><function>lcr.load_gws</function></title>
<para>
Loads gateways and prints ids of matching ones in priority order.
@ -1642,7 +1642,7 @@ if (to_any_gw("192.55.66.2", 1)) {
</example>
</section>
<section>
<section id="lcr.rpc.defunct_gw">
<title><function>lcr.defunct_gw</function></title>
<para>
Defuncts gateway loaded into memory for a period of

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save