mirror of
https://github.com/jambonz/sbc-sip-sidecar.git
synced 2026-10-04 02:04:20 +00:00
feat: merge sip-registra and sip-options-handler
This commit is contained in:
+23
@@ -0,0 +1,23 @@
|
|||||||
|
FROM --platform=linux/amd64 node:18.6.0-alpine as base
|
||||||
|
|
||||||
|
RUN apk --update --no-cache add --virtual .builds-deps build-base python3
|
||||||
|
|
||||||
|
WORKDIR /opt/app/
|
||||||
|
|
||||||
|
FROM base as build
|
||||||
|
|
||||||
|
COPY package.json package-lock.json ./
|
||||||
|
|
||||||
|
RUN npm ci
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
FROM base
|
||||||
|
|
||||||
|
COPY --from=build /opt/app /opt/app/
|
||||||
|
|
||||||
|
ARG NODE_ENV
|
||||||
|
|
||||||
|
ENV NODE_ENV $NODE_ENV
|
||||||
|
|
||||||
|
CMD [ "node", "app.js" ]
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
# sbc-sip-sidecar 
|
||||||
|
|
||||||
|
This application provides a part of the SBC (Session Border Controller) functionality of jambonz. It handles incoming/outgoing REGISTER requests from/to clients/servers (including both sip softphones and WebRTC client applications), incoming OPTIONS. Register Authentication is delegated to customer-side logic via a web callback configured for the account in the jambonz database. Information about active registrations is stored in a redis database.
|
||||||
|
|
||||||
|
## registrar database
|
||||||
|
|
||||||
|
A redis database is used to hold active registrations. When a register request arrives and is authenticated, the following values are parsed from the request:
|
||||||
|
- the address of record, or "aor" (e.g, daveh@drachtio.org),
|
||||||
|
- the sip uri, or "contact" that this user is advertising (e.g. sip:daveh@3.44.3.12:5060)
|
||||||
|
- the source address and port that sent the REGISTER request to the server
|
||||||
|
- the transport protocol that should be used to contact the user (e.g. udp, tcp, wss etc)
|
||||||
|
- the sip address of the drachtio server that received the REGISTER request, and
|
||||||
|
- the expiration of the registration, in seconds.
|
||||||
|
- the application callback that should be invoked when a call is placed from this registered device
|
||||||
|
- the application status callback that should invoked for call events on calls placed from this registered device
|
||||||
|
|
||||||
|
A hash value is created from these values and stored with an expiry value equal to the number of seconds granted to the registration (note that when a sip client is detected as being behind a firewall, the application will reduce the granted expires value to 30 seconds, in order to force the client to re-register frequently, however the expiry in redis is set to the longer, originally requested expires value).
|
||||||
|
|
||||||
|
The hash value is inserted with a key being the aor:
|
||||||
|
```
|
||||||
|
aor => {contact, source, protocol, sbcAddress, call_hook, call_status_hook}, expiry = registration expires value
|
||||||
|
```
|
||||||
|
|
||||||
|
## configuration
|
||||||
|
|
||||||
|
Configuration is provided via the [npmjs config](https://www.npmjs.com/package/config) package. The following elements make up the configuration for the application:
|
||||||
|
##### drachtio server location
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"drachtio": {
|
||||||
|
"port": 3001,
|
||||||
|
"secret": "cymru"
|
||||||
|
},
|
||||||
|
```
|
||||||
|
the `drachtio` object specifies the port to listen on for tcp connections from drachtio servers as well as the shared secret that is used to authenticate to the server.
|
||||||
|
|
||||||
|
> Note: [outbound connections](https://drachtio.org/docs#outbound-connections) are used for all drachtio applications in jambonz, to allow for easier centralization and clustering of application logic.
|
||||||
|
|
||||||
|
##### redis server location
|
||||||
|
```
|
||||||
|
"redis": {
|
||||||
|
"port": 6379,
|
||||||
|
"host": "127.0.0.1"
|
||||||
|
},
|
||||||
|
```
|
||||||
|
the `redis` object specifies the location of the redis database. Any of the options [defined here](https://www.npmjs.com/package/redis#rediscreateclient) may be supplied, but host and port are minimally required.
|
||||||
|
|
||||||
|
Note that in a fully-scaled out environment with multiple SBCs there will be one centralized redis database (or cluster) that stores registrations for all SBCs.
|
||||||
|
|
||||||
|
##### application log level
|
||||||
|
```
|
||||||
|
"logging": {
|
||||||
|
"level": "info"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## http callback
|
||||||
|
Authenticating users is the responsibility of the client by exposing an http callback. A POST request will be sent to the configured callback (i.e. the value in the `accounts.registration_hook` column in the associated sip realm value in the REGISTER request). The body of the POST will be a json payload including the following information:
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"method": "REGISTER",
|
||||||
|
"expires": 3600,
|
||||||
|
"scheme": "digest",
|
||||||
|
"username": "john",
|
||||||
|
"realm": "jambonz.org",
|
||||||
|
"nonce": "157590482938000",
|
||||||
|
"uri": "sip:172.37.0.10:5060",
|
||||||
|
"response": "be641cf7951ff23ab04c57907d59f37d",
|
||||||
|
"qop": "auth",
|
||||||
|
"nc": "00000001",
|
||||||
|
"cnonce": "6b8b4567",
|
||||||
|
"algorithm": "MD5"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
It is the responsibility of the customer-side logic to retrieve the associated password for the given username and to then authenticate the request by calculating a response hash value (per the algorithm described in [RFC 2617](https://tools.ietf.org/html/rfc2617#section-3.2.2)) and comparing it to the response property in the http body.
|
||||||
|
|
||||||
|
For example code showing how to calculate the response hash given the above inputs, [see here](https://github.com/jambonz/customer-auth-server/blob/master/lib/utils.js).
|
||||||
|
|
||||||
|
For a simple, full-fledged example server doing the same, [see here](https://github.com/jambonz/customer-auth-server).
|
||||||
|
|
||||||
|
The customer server SHOULD return a 200 OK response to the http request in all cases with a json body indicating whether the request was successfully authenticated.
|
||||||
|
|
||||||
|
The body MUST include a `status` field with a value of either `ok` or `fail`, indicating whether the request was authenticated or not.
|
||||||
|
```
|
||||||
|
{"status": "ok"}
|
||||||
|
```
|
||||||
|
|
||||||
|
Additionally, in the case of failure, the body MAY include a `msg` field with a human-readable description of why the authentication failed.
|
||||||
|
```
|
||||||
|
{"status": "fail", "msg": "invalid username"}
|
||||||
|
```
|
||||||
|
|
||||||
|
In the case of success, the body MAY include an `expires` value which specifies the duration of time, in seconds, to grant for this registration. If not provided, the expires value in the REGISTER request is used; if provided, however, the value provided must be less than or equal to the duration requested.
|
||||||
|
```
|
||||||
|
{"status": "ok", "expires": 300}
|
||||||
|
```
|
||||||
|
|
||||||
|
Additionally in the case of success, the body SHOULD include `call_hook` and `call_status_hook` properties that reference the application URLs to use when calls are placed from this device. If these values are not provided, outbound calling from the device will not be allowed.
|
||||||
|
|
||||||
|
## Running the test suite
|
||||||
|
To run the included test suite, you will need to have a mysql server installed on your laptop/server. You will need to set the MYSQL_ROOT_PASSWORD env variable to the mysql root password before running the tests. The test suite creates a database named 'jambones_test' in your mysql server to run the tests against, and removes it when done.
|
||||||
|
```
|
||||||
|
MYSQL_ROOT_PASSWORD=foobar npm test
|
||||||
|
```
|
||||||
@@ -7,6 +7,7 @@ assert.ok(process.env.JAMBONES_REDIS_HOST, 'missing JAMBONES_REDIS_HOST env var'
|
|||||||
assert.ok(process.env.DRACHTIO_HOST, 'missing DRACHTIO_HOST env var');
|
assert.ok(process.env.DRACHTIO_HOST, 'missing DRACHTIO_HOST env var');
|
||||||
assert.ok(process.env.DRACHTIO_PORT, 'missing DRACHTIO_PORT env var');
|
assert.ok(process.env.DRACHTIO_PORT, 'missing DRACHTIO_PORT env var');
|
||||||
assert.ok(process.env.DRACHTIO_SECRET, 'missing DRACHTIO_SECRET env var');
|
assert.ok(process.env.DRACHTIO_SECRET, 'missing DRACHTIO_SECRET env var');
|
||||||
|
|
||||||
const opts = Object.assign({
|
const opts = Object.assign({
|
||||||
timestamp: () => { return `, "time": "${new Date().toISOString()}"`; }
|
timestamp: () => { return `, "time": "${new Date().toISOString()}"`; }
|
||||||
}, { level: process.env.JAMBONES_LOGLEVEL || 'info' });
|
}, { level: process.env.JAMBONES_LOGLEVEL || 'info' });
|
||||||
@@ -14,10 +15,21 @@ const logger = require('pino')(opts);
|
|||||||
const Srf = require('drachtio-srf');
|
const Srf = require('drachtio-srf');
|
||||||
const srf = new Srf();
|
const srf = new Srf();
|
||||||
const setName = `${(process.env.JAMBONES_CLUSTER_ID || 'default')}:active-sip`;
|
const setName = `${(process.env.JAMBONES_CLUSTER_ID || 'default')}:active-sip`;
|
||||||
|
const StatsCollector = require('@jambonz/stats-collector');
|
||||||
|
const stats = new StatsCollector(logger);
|
||||||
|
const { initLocals, rejectIpv4, checkCache, checkAccountLimits } = require('./lib/middleware');
|
||||||
|
const responseTime = require('drachtio-mw-response-time');
|
||||||
|
const regParser = require('drachtio-mw-registration-parser');
|
||||||
|
const Registrar = require('@jambonz/mw-registrar');
|
||||||
|
const Emitter = require('events');
|
||||||
|
const debug = require('debug')('jambonz:sbc-registrar');
|
||||||
const {
|
const {
|
||||||
|
lookupAuthHook,
|
||||||
lookupAllVoipCarriers,
|
lookupAllVoipCarriers,
|
||||||
lookupSipGatewaysByCarrier,
|
lookupSipGatewaysByCarrier,
|
||||||
|
lookupAccountBySipRealm,
|
||||||
|
lookupAccountCapacitiesBySid,
|
||||||
|
addSbcAddress
|
||||||
} = require('@jambonz/db-helpers')({
|
} = require('@jambonz/db-helpers')({
|
||||||
host: process.env.JAMBONES_MYSQL_HOST,
|
host: process.env.JAMBONES_MYSQL_HOST,
|
||||||
user: process.env.JAMBONES_MYSQL_USER,
|
user: process.env.JAMBONES_MYSQL_USER,
|
||||||
@@ -25,22 +37,45 @@ const {
|
|||||||
database: process.env.JAMBONES_MYSQL_DATABASE,
|
database: process.env.JAMBONES_MYSQL_DATABASE,
|
||||||
connectionLimit: process.env.JAMBONES_MYSQL_CONNECTION_LIMIT || 10
|
connectionLimit: process.env.JAMBONES_MYSQL_CONNECTION_LIMIT || 10
|
||||||
}, logger);
|
}, logger);
|
||||||
|
const {
|
||||||
|
writeAlerts,
|
||||||
|
AlertType
|
||||||
|
} = require('@jambonz/time-series')(logger, {
|
||||||
|
host: process.env.JAMBONES_TIME_SERIES_HOST,
|
||||||
|
commitSize: 50,
|
||||||
|
commitInterval: 'test' === process.env.NODE_ENV ? 7 : 20
|
||||||
|
});
|
||||||
|
|
||||||
const {
|
const {
|
||||||
retrieveSet } = require('@jambonz/realtimedb-helpers')({
|
addToSet,
|
||||||
|
removeFromSet,
|
||||||
|
isMemberOfSet,
|
||||||
|
retrieveSet
|
||||||
|
} = require('@jambonz/realtimedb-helpers')({
|
||||||
host: process.env.JAMBONES_REDIS_HOST || 'localhost',
|
host: process.env.JAMBONES_REDIS_HOST || 'localhost',
|
||||||
port: process.env.JAMBONES_REDIS_PORT || 6379
|
port: process.env.JAMBONES_REDIS_PORT || 6379
|
||||||
}, logger);
|
}, logger);
|
||||||
|
|
||||||
srf.locals = {
|
srf.locals = {
|
||||||
...srf.locals,
|
...srf.locals,
|
||||||
|
stats,
|
||||||
|
addToSet, removeFromSet, isMemberOfSet, retrieveSet,
|
||||||
|
registrar: new Registrar(logger, {
|
||||||
|
host: process.env.JAMBONES_REDIS_HOST,
|
||||||
|
port: process.env.JAMBONES_REDIS_PORT || 6379
|
||||||
|
}),
|
||||||
dbHelpers: {
|
dbHelpers: {
|
||||||
|
lookupAuthHook,
|
||||||
lookupAllVoipCarriers,
|
lookupAllVoipCarriers,
|
||||||
lookupSipGatewaysByCarrier,
|
lookupSipGatewaysByCarrier,
|
||||||
|
lookupAccountBySipRealm,
|
||||||
|
lookupAccountCapacitiesBySid
|
||||||
},
|
},
|
||||||
realtimeDbHelpers: {
|
realtimeDbHelpers: {
|
||||||
retrieveSet
|
retrieveSet
|
||||||
}
|
},
|
||||||
|
writeAlerts,
|
||||||
|
AlertType
|
||||||
};
|
};
|
||||||
|
|
||||||
srf.connect({ host: process.env.DRACHTIO_HOST, port: process.env.DRACHTIO_PORT, secret: process.env.DRACHTIO_SECRET });
|
srf.connect({ host: process.env.DRACHTIO_HOST, port: process.env.DRACHTIO_PORT, secret: process.env.DRACHTIO_SECRET });
|
||||||
@@ -48,6 +83,17 @@ srf.on('connect', (err, hp) => {
|
|||||||
const ativateRegBot = async(err, hp) => {
|
const ativateRegBot = async(err, hp) => {
|
||||||
if (err) return logger.error({ err }, 'Error connecting to drachtio server');
|
if (err) return logger.error({ err }, 'Error connecting to drachtio server');
|
||||||
logger.info(`connected to drachtio listening on ${hp}`);
|
logger.info(`connected to drachtio listening on ${hp}`);
|
||||||
|
|
||||||
|
// Add SBC Public IP to Database
|
||||||
|
const hostports = hp.split(',');
|
||||||
|
for (const hp of hostports) {
|
||||||
|
const arr = /^(.*)\/(.*):(\d+)$/.exec(hp);
|
||||||
|
if (arr && 'udp' === arr[1]) {
|
||||||
|
logger.info(`adding sbc public address to database: ${arr[2]}`);
|
||||||
|
addSbcAddress(arr[2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Only run when I'm the first member in the set Of Actip Sip SBC
|
// Only run when I'm the first member in the set Of Actip Sip SBC
|
||||||
const set = await retrieveSet(setName);
|
const set = await retrieveSet(setName);
|
||||||
const newArray = Array.from(set);
|
const newArray = Array.from(set);
|
||||||
@@ -80,4 +126,77 @@ if (process.env.NODE_ENV === 'test') {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const rttMetric = (req, res, time) => {
|
||||||
|
if (res.cached) {
|
||||||
|
stats.histogram('sbc.registration.cached.response_time', time.toFixed(0), [`status:${res.statusCode}`]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
stats.histogram('sbc.registration.total.response_time', time.toFixed(0), [`status:${res.statusCode}`]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class RegOutcomeReporter extends Emitter {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this
|
||||||
|
.on('regHookOutcome', ({ rtt, status }) => {
|
||||||
|
stats.histogram('app.hook.response_time', rtt, ['hook_type:auth', `status:${status}`]);
|
||||||
|
if (![200, 403].includes(status)) {
|
||||||
|
stats.increment('app.hook.error.count', ['hook_type:auth', `status:${status}`]);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.on('error', async(err, req) => {
|
||||||
|
logger.error({ err }, 'http webhook failed');
|
||||||
|
const { account_sid } = req.locals;
|
||||||
|
if (account_sid) {
|
||||||
|
let opts = { account_sid };
|
||||||
|
if (err.code === 'ECONNREFUSED') {
|
||||||
|
opts = { ...opts, alert_type: AlertType.WEBHOOK_CONNECTION_FAILURE, url: err.hook };
|
||||||
|
}
|
||||||
|
else if (err.code === 'ENOTFOUND') {
|
||||||
|
opts = { ...opts, alert_type: AlertType.WEBHOOK_CONNECTION_FAILURE, url: err.hook };
|
||||||
|
}
|
||||||
|
else if (err.name === 'StatusError') {
|
||||||
|
opts = { ...opts, alert_type: AlertType.WEBHOOK_STATUS_FAILURE, url: err.hook, status: err.statusCode };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts.alert_type) {
|
||||||
|
try {
|
||||||
|
await writeAlerts(opts);
|
||||||
|
} catch (err) {
|
||||||
|
logger.error({ err, opts }, 'Error writing alert');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const authenticator = require('@jambonz/http-authenticator')(lookupAuthHook, logger, {
|
||||||
|
emitter: new RegOutcomeReporter()
|
||||||
|
});
|
||||||
|
|
||||||
|
// middleware
|
||||||
|
srf.use('register', [
|
||||||
|
initLocals,
|
||||||
|
responseTime(rttMetric),
|
||||||
|
rejectIpv4(logger),
|
||||||
|
regParser,
|
||||||
|
checkCache(logger),
|
||||||
|
checkAccountLimits(logger),
|
||||||
|
authenticator]);
|
||||||
|
|
||||||
|
srf.use('options', [
|
||||||
|
initLocals
|
||||||
|
]);
|
||||||
|
|
||||||
|
srf.register(require('./lib/register')({logger}));
|
||||||
|
srf.options(require('./lib/options')({srf, logger}));
|
||||||
|
|
||||||
|
setInterval(async() => {
|
||||||
|
const count = await srf.locals.registrar.getCountOfUsers();
|
||||||
|
debug(`count of registered users: ${count}`);
|
||||||
|
stats.gauge('sbc.users.count', parseInt(count));
|
||||||
|
}, 30000);
|
||||||
|
|
||||||
module.exports = { srf, logger };
|
module.exports = { srf, logger };
|
||||||
|
|||||||
@@ -0,0 +1,122 @@
|
|||||||
|
const parseUri = require('drachtio-srf').parseUri;
|
||||||
|
const debug = require('debug')('jambonz:sbc-registrar');
|
||||||
|
const {NAT_EXPIRES} = require('./utils');
|
||||||
|
|
||||||
|
const initLocals = (req, res, next) => {
|
||||||
|
req.locals = req.locals || {};
|
||||||
|
next();
|
||||||
|
};
|
||||||
|
|
||||||
|
const rejectIpv4 = (logger) => {
|
||||||
|
return (req, res, next) => {
|
||||||
|
const uri = parseUri(req.uri);
|
||||||
|
if (/^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/.test(uri.host)) {
|
||||||
|
debug(`rejecting REGISTER from ${req.uri} as it has an ipv4 address and sip realm is required`);
|
||||||
|
res.send(403);
|
||||||
|
return req.srf.endSession(req);
|
||||||
|
}
|
||||||
|
next();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const checkCache = (logger) => {
|
||||||
|
return async(req, res, next) => {
|
||||||
|
const registration = req.registration;
|
||||||
|
const uri = parseUri(registration.aor);
|
||||||
|
const aor = `${uri.user}@${uri.host}`;
|
||||||
|
req.locals.realm = uri.host;
|
||||||
|
|
||||||
|
if (registration.type === 'unregister') return next();
|
||||||
|
|
||||||
|
const registrar = req.srf.locals.registrar;
|
||||||
|
const result = await registrar.query(aor);
|
||||||
|
if (result) {
|
||||||
|
// if known valid registration coming from same address, no need to hit the reg callback hook
|
||||||
|
if (result.proxy === `sip:${req.source_address}:${req.source_port}`) {
|
||||||
|
debug(`responding to cached register for ${aor}`);
|
||||||
|
res.cached = true;
|
||||||
|
res.send(200, {
|
||||||
|
headers: {
|
||||||
|
'Contact': req.get('Contact').replace(/expires=\d+/, `expires=${NAT_EXPIRES}`),
|
||||||
|
'Expires': NAT_EXPIRES
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return req.srf.endSession(req);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
next();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const checkAccountLimits = (logger) => {
|
||||||
|
return async(req, res, next) => {
|
||||||
|
|
||||||
|
const {lookupAccountBySipRealm, lookupAccountCapacitiesBySid} = req.srf.locals.dbHelpers;
|
||||||
|
const {realm} = req.locals;
|
||||||
|
const {registrar, writeAlerts, AlertType} = req.srf.locals;
|
||||||
|
try {
|
||||||
|
const account = await lookupAccountBySipRealm(realm);
|
||||||
|
if (account) {
|
||||||
|
req.locals = {
|
||||||
|
...req.locals,
|
||||||
|
account_sid: account.account_sid,
|
||||||
|
webhook_secret: account.webhook_secret
|
||||||
|
};
|
||||||
|
debug(account, `checkAccountLimits: retrieved account for realm: ${realm}`);
|
||||||
|
}
|
||||||
|
else if (process.env.JAMBONES_HOSTING) {
|
||||||
|
debug(`checkAccountLimits: unknown sip realm ${realm}`);
|
||||||
|
logger.info(`checkAccountLimits: rejecting register for unknown sip realm: ${realm}`);
|
||||||
|
return res.send(403);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('unregister' === req.registration.type || !process.env.JAMBONES_HOSTING) return next();
|
||||||
|
|
||||||
|
/* only check limits on the jambonz hosted platform */
|
||||||
|
const {account_sid} = account;
|
||||||
|
const capacities = await lookupAccountCapacitiesBySid(account_sid);
|
||||||
|
debug(JSON.stringify(capacities));
|
||||||
|
const limit_calls = capacities.find((c) => c.category == 'voice_call_session');
|
||||||
|
let limit_registrations = limit_calls.quantity * account.device_to_call_ratio;
|
||||||
|
const extra = capacities.find((c) => c.category == 'device');
|
||||||
|
if (extra && extra.quantity) limit_registrations += extra.quantity;
|
||||||
|
debug(`call capacity: ${limit_calls.quantity}, device capacity: ${limit_registrations}`);
|
||||||
|
|
||||||
|
if (0 === limit_registrations) {
|
||||||
|
debug('checkAccountLimits: device calling not allowed for this account');
|
||||||
|
logger.info({account_sid}, 'checkAccountLimits: device calling not allowed for this account');
|
||||||
|
writeAlerts({
|
||||||
|
alert_type: AlertType.DEVICE_LIMIT,
|
||||||
|
account_sid,
|
||||||
|
count: 0
|
||||||
|
}).catch((err) => logger.info({err}, 'checkAccountLimits: error writing alert'));
|
||||||
|
|
||||||
|
return res.send(503, 'Max Devices Registered');
|
||||||
|
}
|
||||||
|
|
||||||
|
const deviceCount = await registrar.getCountOfUsers(realm);
|
||||||
|
if (deviceCount >= limit_registrations) {
|
||||||
|
debug(account_sid, `checkAccountLimits: limit ${limit_registrations} count ${deviceCount}`);
|
||||||
|
logger.info({account_sid}, 'checkAccountLimits: registration rejected due to limits');
|
||||||
|
writeAlerts({
|
||||||
|
alert_type: AlertType.DEVICE_LIMIT,
|
||||||
|
account_sid,
|
||||||
|
count: limit_registrations
|
||||||
|
}).catch((err) => logger.info({err}, 'checkAccountLimits: error writing alert'));
|
||||||
|
return res.send(503, 'Max Devices Registered');
|
||||||
|
}
|
||||||
|
debug(`checkAccountLimits - passed: devices registered ${deviceCount}, limit is ${limit_registrations}`);
|
||||||
|
next();
|
||||||
|
} catch (err) {
|
||||||
|
logger.error({err, realm}, 'checkAccountLimits: error checking account limits');
|
||||||
|
res.send(500);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
initLocals,
|
||||||
|
rejectIpv4,
|
||||||
|
checkCache,
|
||||||
|
checkAccountLimits
|
||||||
|
};
|
||||||
+118
@@ -0,0 +1,118 @@
|
|||||||
|
const debug = require('debug')('jambonz:sbc-options-handler');
|
||||||
|
const fsServers = new Map();
|
||||||
|
const rtpServers = new Map();
|
||||||
|
|
||||||
|
module.exports = ({srf, logger}) => {
|
||||||
|
const {stats, addToSet, removeFromSet, isMemberOfSet, retrieveSet} = srf.locals;
|
||||||
|
|
||||||
|
const setNameFs = `${(process.env.JAMBONES_CLUSTER_ID || 'default')}:active-fs`;
|
||||||
|
const setNameRtp = `${(process.env.JAMBONES_CLUSTER_ID || 'default')}:active-rtp`;
|
||||||
|
|
||||||
|
/* check for expired servers every so often */
|
||||||
|
setInterval(async() => {
|
||||||
|
const now = Date.now();
|
||||||
|
const expires = process.env.EXPIRES_INTERVAL || 60000;
|
||||||
|
for (const [key, value] of fsServers) {
|
||||||
|
const duration = now - value;
|
||||||
|
if (duration > expires) {
|
||||||
|
fsServers.delete(key);
|
||||||
|
await removeFromSet(setNameFs, key);
|
||||||
|
const members = await retrieveSet(setNameFs);
|
||||||
|
const countOfMembers = members.length;
|
||||||
|
logger.info({members}, `expired member ${key} from ${setNameFs} we now have ${countOfMembers}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const [key, value] of rtpServers) {
|
||||||
|
const duration = now - value;
|
||||||
|
if (duration > expires) {
|
||||||
|
rtpServers.delete(key);
|
||||||
|
await removeFromSet(setNameRtp, key);
|
||||||
|
const members = await retrieveSet(setNameRtp);
|
||||||
|
const countOfMembers = members.length;
|
||||||
|
logger.info({members}, `expired member ${key} from ${setNameRtp} we now have ${countOfMembers}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, process.env.CHECK_EXPIRES_INTERVAL || 20000);
|
||||||
|
|
||||||
|
/* retrieve the initial list of servers, if any, so we can watch them as well */
|
||||||
|
const _init = async() => {
|
||||||
|
try {
|
||||||
|
const now = Date.now();
|
||||||
|
const runningFs = await retrieveSet(setNameFs);
|
||||||
|
const runningRtp = await retrieveSet(setNameRtp);
|
||||||
|
|
||||||
|
if (runningFs.length) {
|
||||||
|
logger.info({runningFs}, 'start watching these FS servers');
|
||||||
|
for (const ip of runningFs) fsServers.set(ip, now);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (runningRtp.length) {
|
||||||
|
logger.info({runningRtp}, 'start watching these RTP servers');
|
||||||
|
for (const ip of runningRtp) rtpServers.set(ip, now);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
logger.error({err}, 'error initializing from redis');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
_init();
|
||||||
|
|
||||||
|
return async(req, res) => {
|
||||||
|
|
||||||
|
/* OPTIONS ping from internal FS or RTP server? */
|
||||||
|
const internal = req.has('X-FS-Status') || req.has('X-RTP-Status');
|
||||||
|
if (!internal) {
|
||||||
|
debug('got external OPTIONS ping');
|
||||||
|
res.send(200);
|
||||||
|
return req.srf.endSession(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
let map, status, countOfMembers;
|
||||||
|
const h = ['X-FS-Status', 'X-RTP-Status'].find((h) => req.has(h));
|
||||||
|
if (h) {
|
||||||
|
const isRtpServer = req.has('X-RTP-Status');
|
||||||
|
const key = isRtpServer ? req.source_address : `${req.source_address}:${req.source_port}`;
|
||||||
|
const prefix = isRtpServer ? 'X-RTP' : 'X-FS';
|
||||||
|
map = isRtpServer ? rtpServers : fsServers;
|
||||||
|
const setName = isRtpServer ? setNameRtp : setNameFs;
|
||||||
|
const gaugeName = isRtpServer ? 'rtpservers' : 'featureservers';
|
||||||
|
|
||||||
|
status = req.get(`${prefix}-Status`);
|
||||||
|
|
||||||
|
if (status === 'open') {
|
||||||
|
map.set(key, Date.now());
|
||||||
|
const exists = await isMemberOfSet(setName, key);
|
||||||
|
if (!exists) {
|
||||||
|
await addToSet(setName, key);
|
||||||
|
const members = await retrieveSet(setName);
|
||||||
|
countOfMembers = members.length;
|
||||||
|
logger.info({members}, `added new member ${key} to ${setName} we now have ${countOfMembers}`);
|
||||||
|
debug({members}, `added new member ${key} to ${setName}`);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const members = await retrieveSet(setName);
|
||||||
|
countOfMembers = members.length;
|
||||||
|
debug(`checkin from existing member ${key} to ${setName}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
map.delete(key);
|
||||||
|
await removeFromSet(setName, key);
|
||||||
|
const members = await retrieveSet(setName);
|
||||||
|
countOfMembers = members.length;
|
||||||
|
logger.info({members}, `removed member ${key} from ${setName} we now have ${countOfMembers}`);
|
||||||
|
debug({members}, `removed member ${key} from ${setName}`);
|
||||||
|
}
|
||||||
|
stats.gauge(gaugeName, map.size);
|
||||||
|
}
|
||||||
|
res.send(200, {headers: {
|
||||||
|
'X-Members': countOfMembers
|
||||||
|
}});
|
||||||
|
} catch (err) {
|
||||||
|
res.send(503);
|
||||||
|
debug(err);
|
||||||
|
logger.error({err}, 'Error handling OPTIONS');
|
||||||
|
}
|
||||||
|
return req.srf.endSession(req);
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
const {isUacBehindNat, getSipProtocol, NAT_EXPIRES} = require('./utils');
|
||||||
|
const parseUri = require('drachtio-srf').parseUri;
|
||||||
|
const debug = require('debug')('jambonz:sbc-registrar');
|
||||||
|
|
||||||
|
module.exports = handler;
|
||||||
|
|
||||||
|
function handler({logger}) {
|
||||||
|
return async(req, res) => {
|
||||||
|
debug(`received ${req.method} from ${req.protocol}/${req.source_address}:${req.source_port}`);
|
||||||
|
|
||||||
|
if ('register' === req.registration.type && '0' !== req.registration.expires) await register(logger, req, res);
|
||||||
|
else await unregister(logger, req, res);
|
||||||
|
|
||||||
|
req.srf.endSession(req);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async function register(logger, req, res) {
|
||||||
|
try {
|
||||||
|
const registrar = req.srf.locals.registrar;
|
||||||
|
const registration = req.registration;
|
||||||
|
const uri = parseUri(registration.aor);
|
||||||
|
const aor = `${uri.user}@${uri.host}`;
|
||||||
|
let expires = req.authorization.grant.expires || registration.expires;
|
||||||
|
const grantedExpires = expires;
|
||||||
|
let contactHdr = req.get('Contact');
|
||||||
|
|
||||||
|
// reduce the registration interval if the device is behind a nat
|
||||||
|
if (isUacBehindNat(req)) {
|
||||||
|
expires = NAT_EXPIRES;
|
||||||
|
contactHdr = contactHdr.replace(/expires=\d+/, `expires=${expires}`);
|
||||||
|
}
|
||||||
|
const opts = {
|
||||||
|
contact: req.getParsedHeader('Contact')[0].uri,
|
||||||
|
sbcAddress: req.server.hostport,
|
||||||
|
protocol: getSipProtocol(req),
|
||||||
|
proxy: `sip:${req.source_address}:${req.source_port}`,
|
||||||
|
callHook: req.authorization.grant.call_hook,
|
||||||
|
callStatusHook: req.authorization.grant.call_status_hook
|
||||||
|
};
|
||||||
|
logger.debug(`adding aor to redis ${aor}`);
|
||||||
|
const result = await registrar.add(aor, opts, grantedExpires);
|
||||||
|
debug(`result ${result} from adding ${JSON.stringify(opts)}`);
|
||||||
|
logger.debug(`successfully added ${aor} to redis, sending 200 OK`);
|
||||||
|
|
||||||
|
res.send(200, {
|
||||||
|
headers: {
|
||||||
|
'Contact': contactHdr,
|
||||||
|
'Expires': expires
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
logger.error({err}, 'Error trying to process REGISTER');
|
||||||
|
if (!res.finalResponseSent) res.send(500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function unregister(logger, req, res) {
|
||||||
|
const registrar = req.srf.locals.registrar;
|
||||||
|
const uri = parseUri(req.registration.aor);
|
||||||
|
const aor = `${uri.user}@${uri.host}`;
|
||||||
|
const result = await registrar.remove(aor);
|
||||||
|
|
||||||
|
logger.debug({result}, `successfully unregistered ${req.registration.aor}`);
|
||||||
|
|
||||||
|
res.send(200, {
|
||||||
|
headers: {
|
||||||
|
'Contact': req.get('Contact'),
|
||||||
|
'Expires': 0
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
function isUacBehindNat(req) {
|
||||||
|
|
||||||
|
// no need for nat handling if wss or tcp being used
|
||||||
|
if (req.protocol !== 'udp') return false;
|
||||||
|
|
||||||
|
// let's keep it simple -- if udp, let's crank down the register interval
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSipProtocol(req) {
|
||||||
|
if (req.getParsedHeader('Via')[0].protocol.toLowerCase().startsWith('wss')) return 'wss';
|
||||||
|
if (req.getParsedHeader('Via')[0].protocol.toLowerCase().startsWith('ws')) return 'ws';
|
||||||
|
if (req.getParsedHeader('Via')[0].protocol.toLowerCase().startsWith('tcp')) return 'tcp';
|
||||||
|
if (req.getParsedHeader('Via')[0].protocol.toLowerCase().startsWith('udp')) return 'udp';
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
isUacBehindNat,
|
||||||
|
getSipProtocol,
|
||||||
|
NAT_EXPIRES: 30
|
||||||
|
};
|
||||||
Generated
+211
@@ -10,8 +10,14 @@
|
|||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jambonz/db-helpers": "^0.6.18",
|
"@jambonz/db-helpers": "^0.6.18",
|
||||||
|
"@jambonz/http-authenticator": "^0.2.1",
|
||||||
|
"@jambonz/mw-registrar": "^0.2.2",
|
||||||
"@jambonz/realtimedb-helpers": "^0.4.29",
|
"@jambonz/realtimedb-helpers": "^0.4.29",
|
||||||
|
"@jambonz/stats-collector": "^0.1.6",
|
||||||
"@jambonz/time-series": "^0.1.12",
|
"@jambonz/time-series": "^0.1.12",
|
||||||
|
"debug": "^4.3.4",
|
||||||
|
"drachtio-mw-registration-parser": "^0.1.0",
|
||||||
|
"drachtio-mw-response-time": "^1.0.2",
|
||||||
"drachtio-srf": "^4.5.17",
|
"drachtio-srf": "^4.5.17",
|
||||||
"pino": "^6.14.0"
|
"pino": "^6.14.0"
|
||||||
},
|
},
|
||||||
@@ -266,6 +272,28 @@
|
|||||||
"uuid": "^8.3.2"
|
"uuid": "^8.3.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@jambonz/http-authenticator": {
|
||||||
|
"version": "0.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jambonz/http-authenticator/-/http-authenticator-0.2.2.tgz",
|
||||||
|
"integrity": "sha512-yl6CajF8c8BOTrXEB/AbTXgqrT6XeymwVZbJWeJG8HZA21UXkKCcM26b8f0P9qqokSvFj0ObjCk22Ks2ytSLNg==",
|
||||||
|
"dependencies": {
|
||||||
|
"bent": "^7.3.12",
|
||||||
|
"debug": "^4.3.1",
|
||||||
|
"drachtio-srf": "^4.4.63",
|
||||||
|
"nonce": "^1.0.4",
|
||||||
|
"qs": "^6.9.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@jambonz/mw-registrar": {
|
||||||
|
"version": "0.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jambonz/mw-registrar/-/mw-registrar-0.2.2.tgz",
|
||||||
|
"integrity": "sha512-CG0MUVRZZ+tBgB5kvjn5IS1R/OdNV5PpAsxCKE0ehe6XVJ1ap4ch9hSZmEh2q7qPnWu8sR451peF33dnoSeaPA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@jambonz/promisify-redis": "^0.0.6",
|
||||||
|
"debug": "^4.3.1",
|
||||||
|
"redis": "^3.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@jambonz/promisify-redis": {
|
"node_modules/@jambonz/promisify-redis": {
|
||||||
"version": "0.0.6",
|
"version": "0.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/@jambonz/promisify-redis/-/promisify-redis-0.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/@jambonz/promisify-redis/-/promisify-redis-0.0.6.tgz",
|
||||||
@@ -291,6 +319,15 @@
|
|||||||
"redis": "^3.1.2"
|
"redis": "^3.1.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@jambonz/stats-collector": {
|
||||||
|
"version": "0.1.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jambonz/stats-collector/-/stats-collector-0.1.6.tgz",
|
||||||
|
"integrity": "sha512-Qk+kpeb2wravpj3OYPC4N3ML1qoAzARNLfKGZtJ05PTAtfWoZMPnyfPAM9EJHIiVfs2Lec3CXDjEpHna0mc9EA==",
|
||||||
|
"dependencies": {
|
||||||
|
"debug": "^4.3.2",
|
||||||
|
"hot-shots": "^8.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@jambonz/time-series": {
|
"node_modules/@jambonz/time-series": {
|
||||||
"version": "0.1.12",
|
"version": "0.1.12",
|
||||||
"resolved": "https://registry.npmjs.org/@jambonz/time-series/-/time-series-0.1.12.tgz",
|
"resolved": "https://registry.npmjs.org/@jambonz/time-series/-/time-series-0.1.12.tgz",
|
||||||
@@ -640,6 +677,15 @@
|
|||||||
"url": "https://bevry.me/fund"
|
"url": "https://bevry.me/fund"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/bindings": {
|
||||||
|
"version": "1.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
|
||||||
|
"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"file-uri-to-path": "1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/bn.js": {
|
"node_modules/bn.js": {
|
||||||
"version": "4.12.0",
|
"version": "4.12.0",
|
||||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
|
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
|
||||||
@@ -887,6 +933,19 @@
|
|||||||
"ignored": "bin/ignored"
|
"ignored": "bin/ignored"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/drachtio-mw-registration-parser": {
|
||||||
|
"version": "0.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/drachtio-mw-registration-parser/-/drachtio-mw-registration-parser-0.1.0.tgz",
|
||||||
|
"integrity": "sha512-SNXEbFjOSuvDCArff/fH4xl1424sQTjPVzNE1Lq5LcyV9sVmW9+/CBBwwkFf1QgEtVUvgTa4w/Jx26Amb3hxaA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6.9.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/drachtio-mw-response-time": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/drachtio-mw-response-time/-/drachtio-mw-response-time-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-d+DtKuqhpkSBBkRfwcgS3x26T3lrdgo86yVWZ4wy+K8RtS1faT3hgLBq9EPEYSDkcw76r4klvdDWPhTrPqGAQw=="
|
||||||
|
},
|
||||||
"node_modules/drachtio-srf": {
|
"node_modules/drachtio-srf": {
|
||||||
"version": "4.5.17",
|
"version": "4.5.17",
|
||||||
"resolved": "https://registry.npmjs.org/drachtio-srf/-/drachtio-srf-4.5.17.tgz",
|
"resolved": "https://registry.npmjs.org/drachtio-srf/-/drachtio-srf-4.5.17.tgz",
|
||||||
@@ -1350,6 +1409,12 @@
|
|||||||
"node": "^10.12.0 || >=12.0.0"
|
"node": "^10.12.0 || >=12.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/file-uri-to-path": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"node_modules/flat-cache": {
|
"node_modules/flat-cache": {
|
||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
|
||||||
@@ -1689,6 +1754,17 @@
|
|||||||
"resolved": "https://registry.npmjs.org/rsvp/-/rsvp-3.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/rsvp/-/rsvp-3.2.1.tgz",
|
||||||
"integrity": "sha512-Rf4YVNYpKjZ6ASAmibcwTNciQ5Co5Ztq6iZPEykHpkoflnD/K5ryE/rHehFsTm4NJj8nKDhbi3eKBWGogmNnkg=="
|
"integrity": "sha512-Rf4YVNYpKjZ6ASAmibcwTNciQ5Co5Ztq6iZPEykHpkoflnD/K5ryE/rHehFsTm4NJj8nKDhbi3eKBWGogmNnkg=="
|
||||||
},
|
},
|
||||||
|
"node_modules/hot-shots": {
|
||||||
|
"version": "8.5.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/hot-shots/-/hot-shots-8.5.2.tgz",
|
||||||
|
"integrity": "sha512-1CKCtbYU28KtRriRW+mdOZzKce0WPqU0FOYE4bYs3gD1bFpOrYzQDXfQ09Qz9dJPEltasDOGhFKiYaiuW/j9Dg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0.0"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"unix-dgram": "2.0.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/https-proxy-agent": {
|
"node_modules/https-proxy-agent": {
|
||||||
"version": "5.0.1",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
|
||||||
@@ -2338,6 +2414,12 @@
|
|||||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
|
||||||
"integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A=="
|
"integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A=="
|
||||||
},
|
},
|
||||||
|
"node_modules/nan": {
|
||||||
|
"version": "2.16.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz",
|
||||||
|
"integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"node_modules/natural-compare": {
|
"node_modules/natural-compare": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
|
||||||
@@ -2376,6 +2458,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/node-noop/-/node-noop-0.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/node-noop/-/node-noop-0.0.1.tgz",
|
||||||
"integrity": "sha512-kAUvIRxZyDYFTLqGj+7zqXduG89vtqGmNMt9qDMvYH3H8uNTCOTz5ZN1q2Yg8++fWbzv+ERtYVqaOH42Ag5OpA=="
|
"integrity": "sha512-kAUvIRxZyDYFTLqGj+7zqXduG89vtqGmNMt9qDMvYH3H8uNTCOTz5ZN1q2Yg8++fWbzv+ERtYVqaOH42Ag5OpA=="
|
||||||
},
|
},
|
||||||
|
"node_modules/nonce": {
|
||||||
|
"version": "1.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/nonce/-/nonce-1.0.4.tgz",
|
||||||
|
"integrity": "sha512-FVPu+tMZPP91HDwiq1DNhn9WIhg4/uo6mXR0xXAn0IMOxDmjJOkgbH0tm7qtowvAFZofWZRX+9KWZpNURrgtSA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/object-hash": {
|
"node_modules/object-hash": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
|
||||||
@@ -2590,6 +2680,20 @@
|
|||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/qs": {
|
||||||
|
"version": "6.11.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
|
||||||
|
"integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
|
||||||
|
"dependencies": {
|
||||||
|
"side-channel": "^1.0.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.6"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/querystring": {
|
"node_modules/querystring": {
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
|
||||||
@@ -3185,6 +3289,20 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/unix-dgram": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/unix-dgram/-/unix-dgram-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-7tpK6x7ls7J7pDrrAU63h93R0dVhRbPwiRRCawR10cl+2e1VOvF3bHlVJc6WI1dl/8qk5He673QU+Ogv7bPNaw==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"bindings": "^1.3.0",
|
||||||
|
"nan": "^2.13.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.48"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/uri-js": {
|
"node_modules/uri-js": {
|
||||||
"version": "4.4.1",
|
"version": "4.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
||||||
@@ -3634,6 +3752,28 @@
|
|||||||
"uuid": "^8.3.2"
|
"uuid": "^8.3.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@jambonz/http-authenticator": {
|
||||||
|
"version": "0.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jambonz/http-authenticator/-/http-authenticator-0.2.2.tgz",
|
||||||
|
"integrity": "sha512-yl6CajF8c8BOTrXEB/AbTXgqrT6XeymwVZbJWeJG8HZA21UXkKCcM26b8f0P9qqokSvFj0ObjCk22Ks2ytSLNg==",
|
||||||
|
"requires": {
|
||||||
|
"bent": "^7.3.12",
|
||||||
|
"debug": "^4.3.1",
|
||||||
|
"drachtio-srf": "^4.4.63",
|
||||||
|
"nonce": "^1.0.4",
|
||||||
|
"qs": "^6.9.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@jambonz/mw-registrar": {
|
||||||
|
"version": "0.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jambonz/mw-registrar/-/mw-registrar-0.2.2.tgz",
|
||||||
|
"integrity": "sha512-CG0MUVRZZ+tBgB5kvjn5IS1R/OdNV5PpAsxCKE0ehe6XVJ1ap4ch9hSZmEh2q7qPnWu8sR451peF33dnoSeaPA==",
|
||||||
|
"requires": {
|
||||||
|
"@jambonz/promisify-redis": "^0.0.6",
|
||||||
|
"debug": "^4.3.1",
|
||||||
|
"redis": "^3.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@jambonz/promisify-redis": {
|
"@jambonz/promisify-redis": {
|
||||||
"version": "0.0.6",
|
"version": "0.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/@jambonz/promisify-redis/-/promisify-redis-0.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/@jambonz/promisify-redis/-/promisify-redis-0.0.6.tgz",
|
||||||
@@ -3656,6 +3796,15 @@
|
|||||||
"redis": "^3.1.2"
|
"redis": "^3.1.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@jambonz/stats-collector": {
|
||||||
|
"version": "0.1.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jambonz/stats-collector/-/stats-collector-0.1.6.tgz",
|
||||||
|
"integrity": "sha512-Qk+kpeb2wravpj3OYPC4N3ML1qoAzARNLfKGZtJ05PTAtfWoZMPnyfPAM9EJHIiVfs2Lec3CXDjEpHna0mc9EA==",
|
||||||
|
"requires": {
|
||||||
|
"debug": "^4.3.2",
|
||||||
|
"hot-shots": "^8.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@jambonz/time-series": {
|
"@jambonz/time-series": {
|
||||||
"version": "0.1.12",
|
"version": "0.1.12",
|
||||||
"resolved": "https://registry.npmjs.org/@jambonz/time-series/-/time-series-0.1.12.tgz",
|
"resolved": "https://registry.npmjs.org/@jambonz/time-series/-/time-series-0.1.12.tgz",
|
||||||
@@ -3924,6 +4073,15 @@
|
|||||||
"resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-2.3.0.tgz",
|
||||||
"integrity": "sha512-nAihlQsYGyc5Bwq6+EsubvANYGExeJKHDO3RjnvwU042fawQTQfM3Kxn7IHUXQOz4bzfwsGYYHGSvXyW4zOGLg=="
|
"integrity": "sha512-nAihlQsYGyc5Bwq6+EsubvANYGExeJKHDO3RjnvwU042fawQTQfM3Kxn7IHUXQOz4bzfwsGYYHGSvXyW4zOGLg=="
|
||||||
},
|
},
|
||||||
|
"bindings": {
|
||||||
|
"version": "1.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
|
||||||
|
"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
|
||||||
|
"optional": true,
|
||||||
|
"requires": {
|
||||||
|
"file-uri-to-path": "1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"bn.js": {
|
"bn.js": {
|
||||||
"version": "4.12.0",
|
"version": "4.12.0",
|
||||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
|
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
|
||||||
@@ -4121,6 +4279,16 @@
|
|||||||
"minimatch": "^3.0.4"
|
"minimatch": "^3.0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"drachtio-mw-registration-parser": {
|
||||||
|
"version": "0.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/drachtio-mw-registration-parser/-/drachtio-mw-registration-parser-0.1.0.tgz",
|
||||||
|
"integrity": "sha512-SNXEbFjOSuvDCArff/fH4xl1424sQTjPVzNE1Lq5LcyV9sVmW9+/CBBwwkFf1QgEtVUvgTa4w/Jx26Amb3hxaA=="
|
||||||
|
},
|
||||||
|
"drachtio-mw-response-time": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/drachtio-mw-response-time/-/drachtio-mw-response-time-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-d+DtKuqhpkSBBkRfwcgS3x26T3lrdgo86yVWZ4wy+K8RtS1faT3hgLBq9EPEYSDkcw76r4klvdDWPhTrPqGAQw=="
|
||||||
|
},
|
||||||
"drachtio-srf": {
|
"drachtio-srf": {
|
||||||
"version": "4.5.17",
|
"version": "4.5.17",
|
||||||
"resolved": "https://registry.npmjs.org/drachtio-srf/-/drachtio-srf-4.5.17.tgz",
|
"resolved": "https://registry.npmjs.org/drachtio-srf/-/drachtio-srf-4.5.17.tgz",
|
||||||
@@ -4481,6 +4649,12 @@
|
|||||||
"flat-cache": "^3.0.4"
|
"flat-cache": "^3.0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"file-uri-to-path": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"flat-cache": {
|
"flat-cache": {
|
||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
|
||||||
@@ -4735,6 +4909,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"hot-shots": {
|
||||||
|
"version": "8.5.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/hot-shots/-/hot-shots-8.5.2.tgz",
|
||||||
|
"integrity": "sha512-1CKCtbYU28KtRriRW+mdOZzKce0WPqU0FOYE4bYs3gD1bFpOrYzQDXfQ09Qz9dJPEltasDOGhFKiYaiuW/j9Dg==",
|
||||||
|
"requires": {
|
||||||
|
"unix-dgram": "2.0.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
"https-proxy-agent": {
|
"https-proxy-agent": {
|
||||||
"version": "5.0.1",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
|
||||||
@@ -5232,6 +5414,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"nan": {
|
||||||
|
"version": "2.16.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz",
|
||||||
|
"integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"natural-compare": {
|
"natural-compare": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
|
||||||
@@ -5256,6 +5444,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/node-noop/-/node-noop-0.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/node-noop/-/node-noop-0.0.1.tgz",
|
||||||
"integrity": "sha512-kAUvIRxZyDYFTLqGj+7zqXduG89vtqGmNMt9qDMvYH3H8uNTCOTz5ZN1q2Yg8++fWbzv+ERtYVqaOH42Ag5OpA=="
|
"integrity": "sha512-kAUvIRxZyDYFTLqGj+7zqXduG89vtqGmNMt9qDMvYH3H8uNTCOTz5ZN1q2Yg8++fWbzv+ERtYVqaOH42Ag5OpA=="
|
||||||
},
|
},
|
||||||
|
"nonce": {
|
||||||
|
"version": "1.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/nonce/-/nonce-1.0.4.tgz",
|
||||||
|
"integrity": "sha512-FVPu+tMZPP91HDwiq1DNhn9WIhg4/uo6mXR0xXAn0IMOxDmjJOkgbH0tm7qtowvAFZofWZRX+9KWZpNURrgtSA=="
|
||||||
|
},
|
||||||
"object-hash": {
|
"object-hash": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
|
||||||
@@ -5420,6 +5613,14 @@
|
|||||||
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
|
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"qs": {
|
||||||
|
"version": "6.11.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
|
||||||
|
"integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
|
||||||
|
"requires": {
|
||||||
|
"side-channel": "^1.0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"querystring": {
|
"querystring": {
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
|
||||||
@@ -5852,6 +6053,16 @@
|
|||||||
"which-boxed-primitive": "^1.0.2"
|
"which-boxed-primitive": "^1.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"unix-dgram": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/unix-dgram/-/unix-dgram-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-7tpK6x7ls7J7pDrrAU63h93R0dVhRbPwiRRCawR10cl+2e1VOvF3bHlVJc6WI1dl/8qk5He673QU+Ogv7bPNaw==",
|
||||||
|
"optional": true,
|
||||||
|
"requires": {
|
||||||
|
"bindings": "^1.3.0",
|
||||||
|
"nan": "^2.13.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"uri-js": {
|
"uri-js": {
|
||||||
"version": "4.4.1",
|
"version": "4.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
||||||
|
|||||||
+7
-1
@@ -28,8 +28,14 @@
|
|||||||
"homepage": "https://github.com/xquanluu/sbc-outbound-handler#readme",
|
"homepage": "https://github.com/xquanluu/sbc-outbound-handler#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jambonz/db-helpers": "^0.6.18",
|
"@jambonz/db-helpers": "^0.6.18",
|
||||||
"@jambonz/realtimedb-helpers": "^0.4.29",
|
"@jambonz/http-authenticator": "^0.2.1",
|
||||||
|
"@jambonz/mw-registrar": "^0.2.2",
|
||||||
|
"@jambonz/stats-collector": "^0.1.6",
|
||||||
"@jambonz/time-series": "^0.1.12",
|
"@jambonz/time-series": "^0.1.12",
|
||||||
|
"debug": "^4.3.4",
|
||||||
|
"drachtio-mw-registration-parser": "^0.1.0",
|
||||||
|
"drachtio-mw-response-time": "^1.0.2",
|
||||||
|
"@jambonz/realtimedb-helpers": "^0.4.29",
|
||||||
"drachtio-srf": "^4.5.17",
|
"drachtio-srf": "^4.5.17",
|
||||||
"pino": "^6.14.0"
|
"pino": "^6.14.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
version: '3'
|
version: '3'
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
sbc-registrar:
|
sbc-sip-sidecar:
|
||||||
driver: bridge
|
driver: bridge
|
||||||
ipam:
|
ipam:
|
||||||
config:
|
config:
|
||||||
@@ -20,7 +20,7 @@ services:
|
|||||||
timeout: 5s
|
timeout: 5s
|
||||||
retries: 10
|
retries: 10
|
||||||
networks:
|
networks:
|
||||||
sbc-registrar:
|
sbc-sip-sidecar:
|
||||||
ipv4_address: 172.39.0.2
|
ipv4_address: 172.39.0.2
|
||||||
sbc:
|
sbc:
|
||||||
image: drachtio/drachtio-server:latest
|
image: drachtio/drachtio-server:latest
|
||||||
@@ -28,17 +28,28 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- "9022:9022/tcp"
|
- "9022:9022/tcp"
|
||||||
networks:
|
networks:
|
||||||
sbc-registrar:
|
sbc-sip-sidecar:
|
||||||
ipv4_address: 172.39.0.10
|
ipv4_address: 172.39.0.10
|
||||||
depends_on:
|
depends_on:
|
||||||
mysql:
|
mysql:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
|
|
||||||
|
auth-server:
|
||||||
|
image: jambonz/customer-auth-server:latest
|
||||||
|
command: npm start
|
||||||
|
ports:
|
||||||
|
- "4000:4000/tcp"
|
||||||
|
env_file: docker.env
|
||||||
|
networks:
|
||||||
|
sbc-sip-sidecar:
|
||||||
|
ipv4_address: 172.39.0.12
|
||||||
|
|
||||||
redis:
|
redis:
|
||||||
image: redis:5-alpine
|
image: redis:5-alpine
|
||||||
ports:
|
ports:
|
||||||
- "16379:6379/tcp"
|
- "16379:6379/tcp"
|
||||||
networks:
|
networks:
|
||||||
sbc-registrar:
|
sbc-sip-sidecar:
|
||||||
ipv4_address: 172.39.0.13
|
ipv4_address: 172.39.0.13
|
||||||
|
|
||||||
sipp-uas-auth-register:
|
sipp-uas-auth-register:
|
||||||
@@ -49,7 +60,7 @@ services:
|
|||||||
- ./scenarios:/tmp
|
- ./scenarios:/tmp
|
||||||
tty: true
|
tty: true
|
||||||
networks:
|
networks:
|
||||||
sbc-registrar:
|
sbc-sip-sidecar:
|
||||||
ipv4_address: 172.39.0.14
|
ipv4_address: 172.39.0.14
|
||||||
|
|
||||||
sipp-uas-auth-register-fail:
|
sipp-uas-auth-register-fail:
|
||||||
@@ -60,5 +71,14 @@ services:
|
|||||||
- ./scenarios:/tmp
|
- ./scenarios:/tmp
|
||||||
tty: true
|
tty: true
|
||||||
networks:
|
networks:
|
||||||
sbc-registrar:
|
sbc-sip-sidecar:
|
||||||
ipv4_address: 172.39.0.15
|
ipv4_address: 172.39.0.15
|
||||||
|
uas:
|
||||||
|
image: drachtio/sipp:latest
|
||||||
|
command: sipp -sf /tmp/uas.xml
|
||||||
|
volumes:
|
||||||
|
- ./scenarios:/tmp
|
||||||
|
tty: true
|
||||||
|
networks:
|
||||||
|
sbc-sip-sidecar:
|
||||||
|
ipv4_address: 172.39.0.60
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
require('./docker_start');
|
require('./docker_start');
|
||||||
require('./create-test-db');
|
require('./create-test-db');
|
||||||
require('./regbot-tests');
|
require('./regbot-tests');
|
||||||
|
require('./sip-register-tests');
|
||||||
|
require('./sip-options-tests');
|
||||||
require('./docker_stop');
|
require('./docker_stop');
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
SEQUENTIAL
|
||||||
|
# user, domain, authentication
|
||||||
|
jane;jambonz.org;[authentication username=jane password=8765]
|
||||||
|
@@ -0,0 +1,3 @@
|
|||||||
|
SEQUENTIAL
|
||||||
|
# user, domain, authentication
|
||||||
|
john;fail.com;[authentication username=john password=1234]
|
||||||
|
@@ -0,0 +1,3 @@
|
|||||||
|
SEQUENTIAL
|
||||||
|
# user, domain, authentication
|
||||||
|
john;jambonz.org;[authentication username=john password=1234]
|
||||||
|
@@ -0,0 +1,3 @@
|
|||||||
|
SEQUENTIAL
|
||||||
|
# user, domain, authentication
|
||||||
|
jane;jambonz.org;[authentication username=jane password=5678]
|
||||||
|
@@ -0,0 +1,50 @@
|
|||||||
|
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||||
|
<!DOCTYPE scenario SYSTEM "sipp.dtd">
|
||||||
|
|
||||||
|
<!-- This program is free software; you can redistribute it and/or -->
|
||||||
|
<!-- modify it under the terms of the GNU General Public License as -->
|
||||||
|
<!-- published by the Free Software Foundation; either version 2 of the -->
|
||||||
|
<!-- License, or (at your option) any later version. -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- This program is distributed in the hope that it will be useful, -->
|
||||||
|
<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->
|
||||||
|
<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -->
|
||||||
|
<!-- GNU General Public License for more details. -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- You should have received a copy of the GNU General Public License -->
|
||||||
|
<!-- along with this program; if not, write to the -->
|
||||||
|
<!-- Free Software Foundation, Inc., -->
|
||||||
|
<!-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- Sipp default 'uac' scenario. -->
|
||||||
|
<!-- -->
|
||||||
|
|
||||||
|
<scenario name="Basic Sipstone UAC">
|
||||||
|
<!-- In client mode (sipp placing calls), the Call-ID MUST be -->
|
||||||
|
<!-- generated by sipp. To do so, use [call_id] keyword. -->
|
||||||
|
<send retrans="500">
|
||||||
|
<![CDATA[
|
||||||
|
|
||||||
|
OPTIONS sip:[service]@[remote_ip]:[remote_port] SIP/2.0
|
||||||
|
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
|
||||||
|
From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]
|
||||||
|
To: [service] <sip:[service]@[remote_ip]:[remote_port]>
|
||||||
|
Call-ID: [call_id]
|
||||||
|
CSeq: 1 OPTIONS
|
||||||
|
Max-Forwards: 70
|
||||||
|
Subject: Performance Test
|
||||||
|
X-FS-Status: open
|
||||||
|
X-FS-Calls: 0
|
||||||
|
Content-Length: 0
|
||||||
|
|
||||||
|
]]>
|
||||||
|
</send>
|
||||||
|
|
||||||
|
<recv response="200" rtd="true">
|
||||||
|
<action>
|
||||||
|
<ereg regexp="1" search_in="hdr" header="X-Members:" check_it="true" assign_to="1"/>
|
||||||
|
<log message="[$1]"/>
|
||||||
|
</action>
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
</scenario>
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||||
|
<!DOCTYPE scenario SYSTEM "sipp.dtd">
|
||||||
|
|
||||||
|
<!-- This program is free software; you can redistribute it and/or -->
|
||||||
|
<!-- modify it under the terms of the GNU General Public License as -->
|
||||||
|
<!-- published by the Free Software Foundation; either version 2 of the -->
|
||||||
|
<!-- License, or (at your option) any later version. -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- This program is distributed in the hope that it will be useful, -->
|
||||||
|
<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->
|
||||||
|
<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -->
|
||||||
|
<!-- GNU General Public License for more details. -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- You should have received a copy of the GNU General Public License -->
|
||||||
|
<!-- along with this program; if not, write to the -->
|
||||||
|
<!-- Free Software Foundation, Inc., -->
|
||||||
|
<!-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- Sipp default 'uac' scenario. -->
|
||||||
|
<!-- -->
|
||||||
|
|
||||||
|
<scenario name="Basic Sipstone UAC">
|
||||||
|
<!-- In client mode (sipp placing calls), the Call-ID MUST be -->
|
||||||
|
<!-- generated by sipp. To do so, use [call_id] keyword. -->
|
||||||
|
<send retrans="500">
|
||||||
|
<![CDATA[
|
||||||
|
|
||||||
|
OPTIONS sip:[service]@[remote_ip]:[remote_port] SIP/2.0
|
||||||
|
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
|
||||||
|
From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]
|
||||||
|
To: [service] <sip:[service]@[remote_ip]:[remote_port]>
|
||||||
|
Call-ID: [call_id]
|
||||||
|
CSeq: 1 OPTIONS
|
||||||
|
Max-Forwards: 70
|
||||||
|
Subject: Performance Test
|
||||||
|
X-FS-Status: open
|
||||||
|
X-FS-Calls: 0
|
||||||
|
Content-Length: 0
|
||||||
|
|
||||||
|
]]>
|
||||||
|
</send>
|
||||||
|
|
||||||
|
<recv response="200" rtd="true">
|
||||||
|
<action>
|
||||||
|
<ereg regexp="2" search_in="hdr" header="X-Members:" check_it="true" assign_to="1"/>
|
||||||
|
<log message="[$1]"/>
|
||||||
|
</action>
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
</scenario>
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||||
|
<!DOCTYPE scenario SYSTEM "sipp.dtd">
|
||||||
|
|
||||||
|
<!-- This program is free software; you can redistribute it and/or -->
|
||||||
|
<!-- modify it under the terms of the GNU General Public License as -->
|
||||||
|
<!-- published by the Free Software Foundation; either version 2 of the -->
|
||||||
|
<!-- License, or (at your option) any later version. -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- This program is distributed in the hope that it will be useful, -->
|
||||||
|
<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->
|
||||||
|
<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -->
|
||||||
|
<!-- GNU General Public License for more details. -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- You should have received a copy of the GNU General Public License -->
|
||||||
|
<!-- along with this program; if not, write to the -->
|
||||||
|
<!-- Free Software Foundation, Inc., -->
|
||||||
|
<!-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- Sipp default 'uac' scenario. -->
|
||||||
|
<!-- -->
|
||||||
|
|
||||||
|
<scenario name="Basic Sipstone UAC">
|
||||||
|
<!-- In client mode (sipp placing calls), the Call-ID MUST be -->
|
||||||
|
<!-- generated by sipp. To do so, use [call_id] keyword. -->
|
||||||
|
<send retrans="500">
|
||||||
|
<![CDATA[
|
||||||
|
|
||||||
|
OPTIONS sip:[service]@[remote_ip]:[remote_port] SIP/2.0
|
||||||
|
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
|
||||||
|
From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]
|
||||||
|
To: [service] <sip:[service]@[remote_ip]:[remote_port]>
|
||||||
|
Call-ID: [call_id]
|
||||||
|
CSeq: 1 OPTIONS
|
||||||
|
Max-Forwards: 70
|
||||||
|
Subject: Performance Test
|
||||||
|
X-RTP-Status: open
|
||||||
|
X-RTP-Calls: 0
|
||||||
|
Content-Length: 0
|
||||||
|
|
||||||
|
]]>
|
||||||
|
</send>
|
||||||
|
|
||||||
|
<recv response="200" rtd="true">
|
||||||
|
<action>
|
||||||
|
<ereg regexp="1" search_in="hdr" header="X-Members:" check_it="true" assign_to="1"/>
|
||||||
|
<log message="[$1]"/>
|
||||||
|
</action>
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
</scenario>
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||||
|
<!DOCTYPE scenario SYSTEM "sipp.dtd">
|
||||||
|
|
||||||
|
<!-- This program is free software; you can redistribute it and/or -->
|
||||||
|
<!-- modify it under the terms of the GNU General Public License as -->
|
||||||
|
<!-- published by the Free Software Foundation; either version 2 of the -->
|
||||||
|
<!-- License, or (at your option) any later version. -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- This program is distributed in the hope that it will be useful, -->
|
||||||
|
<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->
|
||||||
|
<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -->
|
||||||
|
<!-- GNU General Public License for more details. -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- You should have received a copy of the GNU General Public License -->
|
||||||
|
<!-- along with this program; if not, write to the -->
|
||||||
|
<!-- Free Software Foundation, Inc., -->
|
||||||
|
<!-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- Sipp default 'uac' scenario. -->
|
||||||
|
<!-- -->
|
||||||
|
|
||||||
|
<scenario name="Basic Sipstone UAC">
|
||||||
|
<!-- In client mode (sipp placing calls), the Call-ID MUST be -->
|
||||||
|
<!-- generated by sipp. To do so, use [call_id] keyword. -->
|
||||||
|
<send retrans="500">
|
||||||
|
<![CDATA[
|
||||||
|
|
||||||
|
OPTIONS sip:[service]@[remote_ip]:[remote_port] SIP/2.0
|
||||||
|
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
|
||||||
|
From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]
|
||||||
|
To: [service] <sip:[service]@[remote_ip]:[remote_port]>
|
||||||
|
Call-ID: [call_id]
|
||||||
|
CSeq: 1 OPTIONS
|
||||||
|
Max-Forwards: 70
|
||||||
|
Subject: Performance Test
|
||||||
|
X-RTP-Status: open
|
||||||
|
X-RTP-Calls: 0
|
||||||
|
Content-Length: 0
|
||||||
|
|
||||||
|
]]>
|
||||||
|
</send>
|
||||||
|
|
||||||
|
<recv response="200" rtd="true">
|
||||||
|
<action>
|
||||||
|
<ereg regexp="2" search_in="hdr" header="X-Members:" check_it="true" assign_to="1"/>
|
||||||
|
<log message="[$1]"/>
|
||||||
|
</action>
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
</scenario>
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||||
|
<!DOCTYPE scenario SYSTEM "sipp.dtd">
|
||||||
|
|
||||||
|
<!-- This program is free software; you can redistribute it and/or -->
|
||||||
|
<!-- modify it under the terms of the GNU General Public License as -->
|
||||||
|
<!-- published by the Free Software Foundation; either version 2 of the -->
|
||||||
|
<!-- License, or (at your option) any later version. -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- This program is distributed in the hope that it will be useful, -->
|
||||||
|
<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->
|
||||||
|
<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -->
|
||||||
|
<!-- GNU General Public License for more details. -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- You should have received a copy of the GNU General Public License -->
|
||||||
|
<!-- along with this program; if not, write to the -->
|
||||||
|
<!-- Free Software Foundation, Inc., -->
|
||||||
|
<!-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- Sipp default 'uac' scenario. -->
|
||||||
|
<!-- -->
|
||||||
|
|
||||||
|
<scenario name="Basic Sipstone UAC">
|
||||||
|
<!-- In client mode (sipp placing calls), the Call-ID MUST be -->
|
||||||
|
<!-- generated by sipp. To do so, use [call_id] keyword. -->
|
||||||
|
<send retrans="500">
|
||||||
|
<![CDATA[
|
||||||
|
|
||||||
|
OPTIONS sip:[service]@[remote_ip]:[remote_port] SIP/2.0
|
||||||
|
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
|
||||||
|
From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]
|
||||||
|
To: [service] <sip:[service]@[remote_ip]:[remote_port]>
|
||||||
|
Call-ID: [call_id]
|
||||||
|
CSeq: 1 OPTIONS
|
||||||
|
Max-Forwards: 70
|
||||||
|
Subject: Performance Test
|
||||||
|
Content-Length: 0
|
||||||
|
|
||||||
|
]]>
|
||||||
|
</send>
|
||||||
|
|
||||||
|
<recv response="200" rtd="true">
|
||||||
|
<action>
|
||||||
|
<ereg regexp="\d+" search_in="hdr" header="X-Members:" check_it_inverse="true" assign_to="1"/>
|
||||||
|
<log message="[$1]"/>
|
||||||
|
</action>
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
</scenario>
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||||
|
<!DOCTYPE scenario SYSTEM "sipp.dtd">
|
||||||
|
|
||||||
|
<!-- This program is free software; you can redistribute it and/or -->
|
||||||
|
<!-- modify it under the terms of the GNU General Public License as -->
|
||||||
|
<!-- published by the Free Software Foundation; either version 2 of the -->
|
||||||
|
<!-- License, or (at your option) any later version. -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- This program is distributed in the hope that it will be useful, -->
|
||||||
|
<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->
|
||||||
|
<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -->
|
||||||
|
<!-- GNU General Public License for more details. -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- You should have received a copy of the GNU General Public License -->
|
||||||
|
<!-- along with this program; if not, write to the -->
|
||||||
|
<!-- Free Software Foundation, Inc., -->
|
||||||
|
<!-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- Sipp default 'uac' scenario. -->
|
||||||
|
<!-- -->
|
||||||
|
|
||||||
|
<scenario name="Basic Sipstone UAC">
|
||||||
|
<send retrans="500">
|
||||||
|
<![CDATA[
|
||||||
|
REGISTER sip:[field1] SIP/2.0
|
||||||
|
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
|
||||||
|
Max-Forwards: 70
|
||||||
|
From: "sipp" <sip:[field0]@[field1]>;tag=[call_number]
|
||||||
|
To: "sipp" <sip:[field0]@[field1]>
|
||||||
|
Call-ID: reg///[call_id]
|
||||||
|
CSeq: 7 REGISTER
|
||||||
|
Subject: uac-register-auth-failure-expect-403
|
||||||
|
Contact: <sip:sipp@[local_ip]:[local_port]>
|
||||||
|
Expires: 3600
|
||||||
|
Content-Length: 0
|
||||||
|
User-Agent: SIPp
|
||||||
|
]]>
|
||||||
|
</send>
|
||||||
|
|
||||||
|
<recv response="100" optional="true">
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
<recv response="401" auth="true" rtd="true">
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
<send retrans="500">
|
||||||
|
<![CDATA[
|
||||||
|
REGISTER sip:[field1] SIP/2.0
|
||||||
|
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
|
||||||
|
Max-Forwards: 70
|
||||||
|
From: "sipp" <sip:[field0]@[field1]>;tag=[call_number]
|
||||||
|
To: "sipp" <sip:[field0]@[field1]>
|
||||||
|
Call-ID: reg///[call_id]
|
||||||
|
CSeq: 8 REGISTER
|
||||||
|
Subject: uac-register-auth-failure-expect-403
|
||||||
|
Contact: <sip:sipp@[local_ip]:[local_port]>
|
||||||
|
Expires: 3600
|
||||||
|
Content-Length: 0
|
||||||
|
User-Agent: SIPp
|
||||||
|
[field2]
|
||||||
|
]]>
|
||||||
|
</send>
|
||||||
|
|
||||||
|
<recv response="100" optional="true">
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
<recv response="403">
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
<ResponseTimeRepartition value="10, 20"/>
|
||||||
|
<CallLengthRepartition value="10"/>
|
||||||
|
</scenario>
|
||||||
|
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||||
|
<!DOCTYPE scenario SYSTEM "sipp.dtd">
|
||||||
|
|
||||||
|
<scenario name="Basic Sipstone UAC">
|
||||||
|
<send retrans="500">
|
||||||
|
<![CDATA[
|
||||||
|
REGISTER sip:[field1] SIP/2.0
|
||||||
|
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
|
||||||
|
Max-Forwards: 70
|
||||||
|
From: "sipp" <sip:[field0]@[field1]>;tag=[call_number]
|
||||||
|
To: "sipp" <sip:[field0]@[field1]>
|
||||||
|
Call-ID: reg///[call_id]
|
||||||
|
CSeq: 7 REGISTER
|
||||||
|
Subject: uac-register-auth-failure-expect-403
|
||||||
|
Contact: <sip:sipp@[local_ip]:[local_port]>
|
||||||
|
Expires: 3600
|
||||||
|
Content-Length: 0
|
||||||
|
User-Agent: SIPp
|
||||||
|
]]>
|
||||||
|
</send>
|
||||||
|
|
||||||
|
<recv response="100" optional="true">
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
<recv response="503" auth="true" rtd="true">
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
</scenario>
|
||||||
|
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||||
|
<!DOCTYPE scenario SYSTEM "sipp.dtd">
|
||||||
|
|
||||||
|
<scenario name="Basic Sipstone UAC">
|
||||||
|
<send retrans="500">
|
||||||
|
<![CDATA[
|
||||||
|
REGISTER sip:[field1] SIP/2.0
|
||||||
|
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
|
||||||
|
Max-Forwards: 70
|
||||||
|
From: "sipp" <sip:[field0]@[field1]>;tag=[call_number]
|
||||||
|
To: "sipp" <sip:[field0]@[field1]>
|
||||||
|
Call-ID: reg///[call_id]
|
||||||
|
Subject: uac-register-auth-success
|
||||||
|
CSeq: 7 REGISTER
|
||||||
|
Contact: <sip:sipp@[local_ip]:[local_port]>
|
||||||
|
Expires: 3600
|
||||||
|
Content-Length: 0
|
||||||
|
User-Agent: SIPp
|
||||||
|
]]>
|
||||||
|
</send>
|
||||||
|
|
||||||
|
<recv response="100" optional="true">
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
<recv response="401" auth="true" rtd="true">
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
<send retrans="500">
|
||||||
|
<![CDATA[
|
||||||
|
REGISTER sip:[field1] SIP/2.0
|
||||||
|
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
|
||||||
|
Max-Forwards: 70
|
||||||
|
From: "sipp" <sip:[field0]@[field1]>;tag=[call_number]
|
||||||
|
To: "sipp" <sip:[field0]@[field1]>
|
||||||
|
Call-ID: reg///[call_id]
|
||||||
|
CSeq: 8 REGISTER
|
||||||
|
Subject: uac-register-auth-success
|
||||||
|
Contact: <sip:sipp@[local_ip]:[local_port]>
|
||||||
|
Expires: 3600
|
||||||
|
Content-Length: 0
|
||||||
|
User-Agent: SIPp
|
||||||
|
[field2]
|
||||||
|
]]>
|
||||||
|
</send>
|
||||||
|
|
||||||
|
<recv response="100" optional="true">
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
<recv response="200">
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
<ResponseTimeRepartition value="10, 20"/>
|
||||||
|
<CallLengthRepartition value="10"/>
|
||||||
|
</scenario>
|
||||||
|
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||||
|
<!DOCTYPE scenario SYSTEM "sipp.dtd">
|
||||||
|
|
||||||
|
<!-- This program is free software; you can redistribute it and/or -->
|
||||||
|
<!-- modify it under the terms of the GNU General Public License as -->
|
||||||
|
<!-- published by the Free Software Foundation; either version 2 of the -->
|
||||||
|
<!-- License, or (at your option) any later version. -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- This program is distributed in the hope that it will be useful, -->
|
||||||
|
<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->
|
||||||
|
<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -->
|
||||||
|
<!-- GNU General Public License for more details. -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- You should have received a copy of the GNU General Public License -->
|
||||||
|
<!-- along with this program; if not, write to the -->
|
||||||
|
<!-- Free Software Foundation, Inc., -->
|
||||||
|
<!-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- Sipp default 'uac' scenario. -->
|
||||||
|
<!-- -->
|
||||||
|
|
||||||
|
<scenario name="Basic Sipstone UAC">
|
||||||
|
<send retrans="500">
|
||||||
|
<![CDATA[
|
||||||
|
REGISTER sip:[field1] SIP/2.0
|
||||||
|
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
|
||||||
|
Max-Forwards: 70
|
||||||
|
From: "sipp" <sip:[field0]@[field1]>;tag=[call_number]
|
||||||
|
To: "sipp" <sip:[field0]@[field1]>
|
||||||
|
Call-ID: reg2///[call_id]
|
||||||
|
Subject: uac-register-auth-success
|
||||||
|
CSeq: 7 REGISTER
|
||||||
|
Contact: <sip:sipp@[local_ip]:[local_port]>
|
||||||
|
Expires: 5
|
||||||
|
Content-Length: 0
|
||||||
|
User-Agent: SIPp
|
||||||
|
]]>
|
||||||
|
</send>
|
||||||
|
|
||||||
|
<recv response="100" optional="true">
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
<recv response="401" auth="true" rtd="true">
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
<send retrans="500">
|
||||||
|
<![CDATA[
|
||||||
|
REGISTER sip:[field1] SIP/2.0
|
||||||
|
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
|
||||||
|
Max-Forwards: 70
|
||||||
|
From: "sipp" <sip:[field0]@[field1]>;tag=[call_number]
|
||||||
|
To: "sipp" <sip:[field0]@[field1]>
|
||||||
|
Call-ID: reg2///[call_id]
|
||||||
|
CSeq: 8 REGISTER
|
||||||
|
Subject: uac-register-auth-success
|
||||||
|
Contact: <sip:sipp@[local_ip]:[local_port]>
|
||||||
|
Expires: 5
|
||||||
|
Content-Length: 0
|
||||||
|
User-Agent: SIPp
|
||||||
|
[field2]
|
||||||
|
]]>
|
||||||
|
</send>
|
||||||
|
|
||||||
|
<recv response="100" optional="true">
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
<recv response="200">
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
<ResponseTimeRepartition value="10, 20"/>
|
||||||
|
<CallLengthRepartition value="10"/>
|
||||||
|
</scenario>
|
||||||
|
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||||
|
<!DOCTYPE scenario SYSTEM "sipp.dtd">
|
||||||
|
|
||||||
|
<scenario name="Basic Sipstone UAC">
|
||||||
|
<send retrans="500">
|
||||||
|
<![CDATA[
|
||||||
|
REGISTER sip:[field1] SIP/2.0
|
||||||
|
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
|
||||||
|
Max-Forwards: 70
|
||||||
|
From: "sipp" <sip:[field0]@[field1]>;tag=[call_number]
|
||||||
|
To: "sipp" <sip:[field0]@[field1]>
|
||||||
|
Call-ID: reg///[call_id]
|
||||||
|
CSeq: 7 REGISTER
|
||||||
|
Contact: <sip:sipp@[local_ip]:[local_port]>
|
||||||
|
Expires: 3600
|
||||||
|
Content-Length: 0
|
||||||
|
User-Agent: SIPp
|
||||||
|
]]>
|
||||||
|
</send>
|
||||||
|
|
||||||
|
<recv response="100" optional="true">
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
<recv response="403">
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
</scenario>
|
||||||
|
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||||
|
<!DOCTYPE scenario SYSTEM "sipp.dtd">
|
||||||
|
|
||||||
|
<scenario name="Basic Sipstone UAC">
|
||||||
|
<send retrans="500">
|
||||||
|
<![CDATA[
|
||||||
|
REGISTER sip:192.169.1.1 SIP/2.0
|
||||||
|
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
|
||||||
|
Max-Forwards: 70
|
||||||
|
From: "sipp" <sip:[field0]@[field1]>;tag=[call_number]
|
||||||
|
To: "sipp" <sip:[field0]@[field1]>
|
||||||
|
Call-ID: reg///[call_id]
|
||||||
|
CSeq: 7 REGISTER
|
||||||
|
Contact: <sip:sipp@[local_ip]:[local_port]>
|
||||||
|
Expires: 3600
|
||||||
|
Content-Length: 0
|
||||||
|
User-Agent: SIPp
|
||||||
|
]]>
|
||||||
|
</send>
|
||||||
|
|
||||||
|
<recv response="100" optional="true">
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
<recv response="403">
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
</scenario>
|
||||||
|
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||||
|
<!DOCTYPE scenario SYSTEM "sipp.dtd">
|
||||||
|
|
||||||
|
<!-- This program is free software; you can redistribute it and/or -->
|
||||||
|
<!-- modify it under the terms of the GNU General Public License as -->
|
||||||
|
<!-- published by the Free Software Foundation; either version 2 of the -->
|
||||||
|
<!-- License, or (at your option) any later version. -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- This program is distributed in the hope that it will be useful, -->
|
||||||
|
<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->
|
||||||
|
<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -->
|
||||||
|
<!-- GNU General Public License for more details. -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- You should have received a copy of the GNU General Public License -->
|
||||||
|
<!-- along with this program; if not, write to the -->
|
||||||
|
<!-- Free Software Foundation, Inc., -->
|
||||||
|
<!-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- Sipp default 'uac' scenario. -->
|
||||||
|
<!-- -->
|
||||||
|
|
||||||
|
<scenario name="Basic Sipstone UAC">
|
||||||
|
<!-- In client mode (sipp placing calls), the Call-ID MUST be -->
|
||||||
|
<!-- generated by sipp. To do so, use [call_id] keyword. -->
|
||||||
|
<send retrans="500">
|
||||||
|
<![CDATA[
|
||||||
|
|
||||||
|
OPTIONS sip:[service]@[remote_ip]:[remote_port] SIP/2.0
|
||||||
|
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
|
||||||
|
From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]
|
||||||
|
To: [service] <sip:[service]@[remote_ip]:[remote_port]>
|
||||||
|
Call-ID: [call_id]
|
||||||
|
CSeq: 1 OPTIONS
|
||||||
|
Max-Forwards: 70
|
||||||
|
Subject: Performance Test
|
||||||
|
X-FS-Status: closed
|
||||||
|
X-FS-Calls: 0
|
||||||
|
Content-Length: 0
|
||||||
|
|
||||||
|
]]>
|
||||||
|
</send>
|
||||||
|
|
||||||
|
<recv response="200" rtd="true">
|
||||||
|
<action>
|
||||||
|
<ereg regexp="1" search_in="hdr" header="X-Members:" check_it="true" assign_to="1"/>
|
||||||
|
<log message="[$1]"/>
|
||||||
|
</action>
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
</scenario>
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||||
|
<!DOCTYPE scenario SYSTEM "sipp.dtd">
|
||||||
|
|
||||||
|
<!-- This program is free software; you can redistribute it and/or -->
|
||||||
|
<!-- modify it under the terms of the GNU General Public License as -->
|
||||||
|
<!-- published by the Free Software Foundation; either version 2 of the -->
|
||||||
|
<!-- License, or (at your option) any later version. -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- This program is distributed in the hope that it will be useful, -->
|
||||||
|
<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->
|
||||||
|
<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -->
|
||||||
|
<!-- GNU General Public License for more details. -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- You should have received a copy of the GNU General Public License -->
|
||||||
|
<!-- along with this program; if not, write to the -->
|
||||||
|
<!-- Free Software Foundation, Inc., -->
|
||||||
|
<!-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- Sipp default 'uac' scenario. -->
|
||||||
|
<!-- -->
|
||||||
|
|
||||||
|
<scenario name="Basic Sipstone UAC">
|
||||||
|
<!-- In client mode (sipp placing calls), the Call-ID MUST be -->
|
||||||
|
<!-- generated by sipp. To do so, use [call_id] keyword. -->
|
||||||
|
<send retrans="500">
|
||||||
|
<![CDATA[
|
||||||
|
|
||||||
|
OPTIONS sip:[service]@[remote_ip]:[remote_port] SIP/2.0
|
||||||
|
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
|
||||||
|
From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]
|
||||||
|
To: [service] <sip:[service]@[remote_ip]:[remote_port]>
|
||||||
|
Call-ID: [call_id]
|
||||||
|
CSeq: 1 OPTIONS
|
||||||
|
Max-Forwards: 70
|
||||||
|
Subject: Performance Test
|
||||||
|
X-FS-Status: closed
|
||||||
|
X-FS-Calls: 0
|
||||||
|
Content-Length: 0
|
||||||
|
|
||||||
|
]]>
|
||||||
|
</send>
|
||||||
|
|
||||||
|
<recv response="200" rtd="true">
|
||||||
|
<action>
|
||||||
|
<ereg regexp="0" search_in="hdr" header="X-Members:" check_it="true" assign_to="1"/>
|
||||||
|
<log message="[$1]"/>
|
||||||
|
</action>
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
</scenario>
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||||
|
<!DOCTYPE scenario SYSTEM "sipp.dtd">
|
||||||
|
|
||||||
|
<!-- This program is free software; you can redistribute it and/or -->
|
||||||
|
<!-- modify it under the terms of the GNU General Public License as -->
|
||||||
|
<!-- published by the Free Software Foundation; either version 2 of the -->
|
||||||
|
<!-- License, or (at your option) any later version. -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- This program is distributed in the hope that it will be useful, -->
|
||||||
|
<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->
|
||||||
|
<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -->
|
||||||
|
<!-- GNU General Public License for more details. -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- You should have received a copy of the GNU General Public License -->
|
||||||
|
<!-- along with this program; if not, write to the -->
|
||||||
|
<!-- Free Software Foundation, Inc., -->
|
||||||
|
<!-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- Sipp default 'uac' scenario. -->
|
||||||
|
<!-- -->
|
||||||
|
|
||||||
|
<scenario name="Basic Sipstone UAC">
|
||||||
|
<!-- In client mode (sipp placing calls), the Call-ID MUST be -->
|
||||||
|
<!-- generated by sipp. To do so, use [call_id] keyword. -->
|
||||||
|
<send retrans="500">
|
||||||
|
<![CDATA[
|
||||||
|
|
||||||
|
OPTIONS sip:[service]@[remote_ip]:[remote_port] SIP/2.0
|
||||||
|
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
|
||||||
|
From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]
|
||||||
|
To: [service] <sip:[service]@[remote_ip]:[remote_port]>
|
||||||
|
Call-ID: [call_id]
|
||||||
|
CSeq: 1 OPTIONS
|
||||||
|
Max-Forwards: 70
|
||||||
|
Subject: Performance Test
|
||||||
|
X-RTP-Status: closed
|
||||||
|
X-RTP-Calls: 0
|
||||||
|
Content-Length: 0
|
||||||
|
|
||||||
|
]]>
|
||||||
|
</send>
|
||||||
|
|
||||||
|
<recv response="200" rtd="true">
|
||||||
|
<action>
|
||||||
|
<ereg regexp="1" search_in="hdr" header="X-Members:" check_it="true" assign_to="1"/>
|
||||||
|
<log message="[$1]"/>
|
||||||
|
</action>
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
</scenario>
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||||
|
<!DOCTYPE scenario SYSTEM "sipp.dtd">
|
||||||
|
|
||||||
|
<!-- This program is free software; you can redistribute it and/or -->
|
||||||
|
<!-- modify it under the terms of the GNU General Public License as -->
|
||||||
|
<!-- published by the Free Software Foundation; either version 2 of the -->
|
||||||
|
<!-- License, or (at your option) any later version. -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- This program is distributed in the hope that it will be useful, -->
|
||||||
|
<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->
|
||||||
|
<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -->
|
||||||
|
<!-- GNU General Public License for more details. -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- You should have received a copy of the GNU General Public License -->
|
||||||
|
<!-- along with this program; if not, write to the -->
|
||||||
|
<!-- Free Software Foundation, Inc., -->
|
||||||
|
<!-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- Sipp default 'uac' scenario. -->
|
||||||
|
<!-- -->
|
||||||
|
|
||||||
|
<scenario name="Basic Sipstone UAC">
|
||||||
|
<!-- In client mode (sipp placing calls), the Call-ID MUST be -->
|
||||||
|
<!-- generated by sipp. To do so, use [call_id] keyword. -->
|
||||||
|
<send retrans="500">
|
||||||
|
<![CDATA[
|
||||||
|
|
||||||
|
OPTIONS sip:[service]@[remote_ip]:[remote_port] SIP/2.0
|
||||||
|
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
|
||||||
|
From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]
|
||||||
|
To: [service] <sip:[service]@[remote_ip]:[remote_port]>
|
||||||
|
Call-ID: [call_id]
|
||||||
|
CSeq: 1 OPTIONS
|
||||||
|
Max-Forwards: 70
|
||||||
|
Subject: Performance Test
|
||||||
|
X-RTP-Status: closed
|
||||||
|
X-RTP-Calls: 0
|
||||||
|
Content-Length: 0
|
||||||
|
|
||||||
|
]]>
|
||||||
|
</send>
|
||||||
|
|
||||||
|
<recv response="200" rtd="true">
|
||||||
|
<action>
|
||||||
|
<ereg regexp="0" search_in="hdr" header="X-Members:" check_it="true" assign_to="1"/>
|
||||||
|
<log message="[$1]"/>
|
||||||
|
</action>
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
</scenario>
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||||
|
<!DOCTYPE scenario SYSTEM "sipp.dtd">
|
||||||
|
|
||||||
|
<!-- This program is free software; you can redistribute it and/or -->
|
||||||
|
<!-- modify it under the terms of the GNU General Public License as -->
|
||||||
|
<!-- published by the Free Software Foundation; either version 2 of the -->
|
||||||
|
<!-- License, or (at your option) any later version. -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- This program is distributed in the hope that it will be useful, -->
|
||||||
|
<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->
|
||||||
|
<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -->
|
||||||
|
<!-- GNU General Public License for more details. -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- You should have received a copy of the GNU General Public License -->
|
||||||
|
<!-- along with this program; if not, write to the -->
|
||||||
|
<!-- Free Software Foundation, Inc., -->
|
||||||
|
<!-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- Sipp default 'uac' scenario. -->
|
||||||
|
<!-- -->
|
||||||
|
|
||||||
|
<scenario name="Basic Sipstone UAC">
|
||||||
|
<send retrans="500">
|
||||||
|
<![CDATA[
|
||||||
|
REGISTER sip:[field1] SIP/2.0
|
||||||
|
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
|
||||||
|
Max-Forwards: 70
|
||||||
|
From: "sipp" <sip:[field0]@[field1]>;tag=[call_number]
|
||||||
|
To: "sipp" <sip:[field0]@[field1]>
|
||||||
|
Call-ID: reg///[call_id]
|
||||||
|
CSeq: 7 REGISTER
|
||||||
|
Contact: <sip:sipp@[local_ip]:[local_port]>
|
||||||
|
Expires: 0
|
||||||
|
Content-Length: 0
|
||||||
|
User-Agent: SIPp
|
||||||
|
]]>
|
||||||
|
</send>
|
||||||
|
|
||||||
|
<recv response="100" optional="true">
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
<recv response="401" auth="true" rtd="true">
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
<send retrans="500">
|
||||||
|
<![CDATA[
|
||||||
|
REGISTER sip:[field1] SIP/2.0
|
||||||
|
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
|
||||||
|
Max-Forwards: 70
|
||||||
|
From: "sipp" <sip:[field0]@[field1]>;tag=[call_number]
|
||||||
|
To: "sipp" <sip:[field0]@[field1]>
|
||||||
|
Call-ID: reg///[call_id]
|
||||||
|
CSeq: 8 REGISTER
|
||||||
|
Contact: <sip:sipp@[local_ip]:[local_port]>
|
||||||
|
Expires: 0
|
||||||
|
Content-Length: 0
|
||||||
|
User-Agent: SIPp
|
||||||
|
[field2]
|
||||||
|
]]>
|
||||||
|
</send>
|
||||||
|
|
||||||
|
<recv response="100" optional="true">
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
<recv response="200">
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
<ResponseTimeRepartition value="10, 20"/>
|
||||||
|
<CallLengthRepartition value="10"/>
|
||||||
|
</scenario>
|
||||||
|
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||||
|
<!DOCTYPE scenario SYSTEM "sipp.dtd">
|
||||||
|
|
||||||
|
<!-- This program is free software; you can redistribute it and/or -->
|
||||||
|
<!-- modify it under the terms of the GNU General Public License as -->
|
||||||
|
<!-- published by the Free Software Foundation; either version 2 of the -->
|
||||||
|
<!-- License, or (at your option) any later version. -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- This program is distributed in the hope that it will be useful, -->
|
||||||
|
<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->
|
||||||
|
<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -->
|
||||||
|
<!-- GNU General Public License for more details. -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- You should have received a copy of the GNU General Public License -->
|
||||||
|
<!-- along with this program; if not, write to the -->
|
||||||
|
<!-- Free Software Foundation, Inc., -->
|
||||||
|
<!-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- Sipp default 'uas' scenario. -->
|
||||||
|
<!-- -->
|
||||||
|
|
||||||
|
<scenario name="Basic UAS responder">
|
||||||
|
<!-- By adding rrs="true" (Record Route Sets), the route sets -->
|
||||||
|
<!-- are saved and used for following messages sent. Useful to test -->
|
||||||
|
<!-- against stateful SIP proxies/B2BUAs. -->
|
||||||
|
<recv request="REGISTER" crlf="true">
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
<send>
|
||||||
|
<![CDATA[
|
||||||
|
|
||||||
|
SIP/2.0 401 Unauthorized
|
||||||
|
[last_Via:]
|
||||||
|
[last_From:]
|
||||||
|
[last_To:];tag=[pid]SIPpTag01[call_number]
|
||||||
|
[last_Call-ID:]
|
||||||
|
[last_CSeq:]
|
||||||
|
WWW-Authenticate: Digest realm="sip.jambonz.org", nonce="4cdbb733645816512687270b83d2ae5d11e4d9d8"
|
||||||
|
Content-Length: 0
|
||||||
|
|
||||||
|
]]>
|
||||||
|
</send>
|
||||||
|
|
||||||
|
<recv request="REGISTER" crlf="true">
|
||||||
|
<action>
|
||||||
|
<verifyauth assign_to="authvalid" username="foo" password="bar" />
|
||||||
|
</action>
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
<nop hide="true" test="authvalid" next="goodauth" />
|
||||||
|
|
||||||
|
<send next="endit">
|
||||||
|
<![CDATA[
|
||||||
|
|
||||||
|
SIP/2.0 403 Forbidden
|
||||||
|
[last_Via:]
|
||||||
|
[last_From:]
|
||||||
|
[last_To:];tag=[pid]SIPpTag01[call_number]
|
||||||
|
[last_Call-ID:]
|
||||||
|
[last_CSeq:]
|
||||||
|
Contact: <sip:[local_ip]:[local_port];transport=[transport]>;expires=60
|
||||||
|
Content-Type: application/sdp
|
||||||
|
Content-Length: 0
|
||||||
|
|
||||||
|
]]>
|
||||||
|
</send>
|
||||||
|
|
||||||
|
<label id="goodauth"/>
|
||||||
|
<send>
|
||||||
|
<![CDATA[
|
||||||
|
|
||||||
|
SIP/2.0 200 OK
|
||||||
|
[last_Via:]
|
||||||
|
[last_From:]
|
||||||
|
[last_To:];tag=[pid]SIPpTag01[call_number]
|
||||||
|
[last_Call-ID:]
|
||||||
|
[last_CSeq:]
|
||||||
|
Contact: <sip:[local_ip]:[local_port];transport=[transport]>;expires=60
|
||||||
|
Content-Type: application/sdp
|
||||||
|
Content-Length: 0
|
||||||
|
|
||||||
|
]]>
|
||||||
|
</send>
|
||||||
|
|
||||||
|
<label id="badauth"/>
|
||||||
|
|
||||||
|
<label id="endit"/>
|
||||||
|
|
||||||
|
<!-- Keep the call open for a while in case the 200 is lost to be -->
|
||||||
|
<!-- able to retransmit it if we receive the BYE again. -->
|
||||||
|
<timewait milliseconds="4000"/>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- definition of the response time repartition table (unit is ms) -->
|
||||||
|
<ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/>
|
||||||
|
|
||||||
|
<!-- definition of the call length repartition table (unit is ms) -->
|
||||||
|
<CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/>
|
||||||
|
|
||||||
|
</scenario>
|
||||||
|
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||||
|
<!DOCTYPE scenario SYSTEM "sipp.dtd">
|
||||||
|
|
||||||
|
<!-- This program is free software; you can redistribute it and/or -->
|
||||||
|
<!-- modify it under the terms of the GNU General Public License as -->
|
||||||
|
<!-- published by the Free Software Foundation; either version 2 of the -->
|
||||||
|
<!-- License, or (at your option) any later version. -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- This program is distributed in the hope that it will be useful, -->
|
||||||
|
<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->
|
||||||
|
<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -->
|
||||||
|
<!-- GNU General Public License for more details. -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- You should have received a copy of the GNU General Public License -->
|
||||||
|
<!-- along with this program; if not, write to the -->
|
||||||
|
<!-- Free Software Foundation, Inc., -->
|
||||||
|
<!-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- Sipp default 'uas' scenario. -->
|
||||||
|
<!-- -->
|
||||||
|
|
||||||
|
<scenario name="Basic UAS responder">
|
||||||
|
<!-- By adding rrs="true" (Record Route Sets), the route sets -->
|
||||||
|
<!-- are saved and used for following messages sent. Useful to test -->
|
||||||
|
<!-- against stateful SIP proxies/B2BUAs. -->
|
||||||
|
<recv request="REGISTER" crlf="true">
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
<send>
|
||||||
|
<![CDATA[
|
||||||
|
|
||||||
|
SIP/2.0 401 Unauthorized
|
||||||
|
[last_Via:]
|
||||||
|
[last_From:]
|
||||||
|
[last_To:];tag=[pid]SIPpTag01[call_number]
|
||||||
|
[last_Call-ID:]
|
||||||
|
[last_CSeq:]
|
||||||
|
WWW-Authenticate: Digest realm="sip.jambonz.org", nonce="4cdbb733645816512687270b83d2ae5d11e4d9d8"
|
||||||
|
Content-Length: 0
|
||||||
|
|
||||||
|
]]>
|
||||||
|
</send>
|
||||||
|
|
||||||
|
<recv request="REGISTER" crlf="true">
|
||||||
|
<action>
|
||||||
|
<verifyauth assign_to="authvalid" username="foo" password="baz" />
|
||||||
|
</action>
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
<nop hide="true" test="authvalid" next="goodauth" />
|
||||||
|
|
||||||
|
<send next="endit">
|
||||||
|
<![CDATA[
|
||||||
|
|
||||||
|
SIP/2.0 403 Forbidden
|
||||||
|
[last_Via:]
|
||||||
|
[last_From:]
|
||||||
|
[last_To:];tag=[pid]SIPpTag01[call_number]
|
||||||
|
[last_Call-ID:]
|
||||||
|
[last_CSeq:]
|
||||||
|
Contact: <sip:[local_ip]:[local_port];transport=[transport]>;expires=60
|
||||||
|
Content-Type: application/sdp
|
||||||
|
Content-Length: 0
|
||||||
|
|
||||||
|
]]>
|
||||||
|
</send>
|
||||||
|
|
||||||
|
<label id="goodauth"/>
|
||||||
|
<send>
|
||||||
|
<![CDATA[
|
||||||
|
|
||||||
|
SIP/2.0 200 OK
|
||||||
|
[last_Via:]
|
||||||
|
[last_From:]
|
||||||
|
[last_To:];tag=[pid]SIPpTag01[call_number]
|
||||||
|
[last_Call-ID:]
|
||||||
|
[last_CSeq:]
|
||||||
|
Contact: <sip:[local_ip]:[local_port];transport=[transport]>;expires=60
|
||||||
|
Content-Type: application/sdp
|
||||||
|
Content-Length: 0
|
||||||
|
|
||||||
|
]]>
|
||||||
|
</send>
|
||||||
|
|
||||||
|
<label id="badauth"/>
|
||||||
|
|
||||||
|
<label id="endit"/>
|
||||||
|
|
||||||
|
<!-- Keep the call open for a while in case the 200 is lost to be -->
|
||||||
|
<!-- able to retransmit it if we receive the BYE again. -->
|
||||||
|
<timewait milliseconds="4000"/>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- definition of the response time repartition table (unit is ms) -->
|
||||||
|
<ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/>
|
||||||
|
|
||||||
|
<!-- definition of the call length repartition table (unit is ms) -->
|
||||||
|
<CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/>
|
||||||
|
|
||||||
|
</scenario>
|
||||||
|
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||||
|
<!DOCTYPE scenario SYSTEM "sipp.dtd">
|
||||||
|
|
||||||
|
<!-- This program is free software; you can redistribute it and/or -->
|
||||||
|
<!-- modify it under the terms of the GNU General Public License as -->
|
||||||
|
<!-- published by the Free Software Foundation; either version 2 of the -->
|
||||||
|
<!-- License, or (at your option) any later version. -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- This program is distributed in the hope that it will be useful, -->
|
||||||
|
<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->
|
||||||
|
<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -->
|
||||||
|
<!-- GNU General Public License for more details. -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- You should have received a copy of the GNU General Public License -->
|
||||||
|
<!-- along with this program; if not, write to the -->
|
||||||
|
<!-- Free Software Foundation, Inc., -->
|
||||||
|
<!-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- Sipp default 'uas' scenario. -->
|
||||||
|
<!-- -->
|
||||||
|
|
||||||
|
<scenario name="Basic UAS responder">
|
||||||
|
<!-- By adding rrs="true" (Record Route Sets), the route sets -->
|
||||||
|
<!-- are saved and used for following messages sent. Useful to test -->
|
||||||
|
<!-- against stateful SIP proxies/B2BUAs. -->
|
||||||
|
<recv request="INVITE" crlf="true">
|
||||||
|
<action>
|
||||||
|
<ereg regexp=".*" search_in="hdr" header="Subject:" assign_to="1" />
|
||||||
|
</action>
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
<!-- The '[last_*]' keyword is replaced automatically by the -->
|
||||||
|
<!-- specified header if it was present in the last message received -->
|
||||||
|
<!-- (except if it was a retransmission). If the header was not -->
|
||||||
|
<!-- present or if no message has been received, the '[last_*]' -->
|
||||||
|
<!-- keyword is discarded, and all bytes until the end of the line -->
|
||||||
|
<!-- are also discarded. -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- If the specified header was present several times in the -->
|
||||||
|
<!-- message, all occurrences are concatenated (CRLF separated) -->
|
||||||
|
<!-- to be used in place of the '[last_*]' keyword. -->
|
||||||
|
|
||||||
|
<send>
|
||||||
|
<![CDATA[
|
||||||
|
|
||||||
|
SIP/2.0 180 Ringing
|
||||||
|
[last_Via:]
|
||||||
|
[last_From:]
|
||||||
|
[last_To:];tag=[pid]SIPpTag01[call_number]
|
||||||
|
[last_Call-ID:]
|
||||||
|
[last_CSeq:]
|
||||||
|
[last_Record-Route:]
|
||||||
|
Subject:[$1]
|
||||||
|
Content-Length: 0
|
||||||
|
|
||||||
|
]]>
|
||||||
|
</send>
|
||||||
|
|
||||||
|
<send>
|
||||||
|
<![CDATA[
|
||||||
|
|
||||||
|
SIP/2.0 200 OK
|
||||||
|
[last_Via:]
|
||||||
|
[last_From:]
|
||||||
|
[last_To:];tag=[pid]SIPpTag01[call_number]
|
||||||
|
[last_Call-ID:]
|
||||||
|
[last_CSeq:]
|
||||||
|
[last_Record-Route:]
|
||||||
|
Subject:[$1]
|
||||||
|
Contact: <sip:[local_ip]:[local_port];transport=[transport]>
|
||||||
|
Content-Type: application/sdp
|
||||||
|
Content-Length: [len]
|
||||||
|
|
||||||
|
v=0
|
||||||
|
o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]
|
||||||
|
s=-
|
||||||
|
c=IN IP[media_ip_type] [media_ip]
|
||||||
|
t=0 0
|
||||||
|
m=audio [media_port] RTP/AVP 0
|
||||||
|
a=rtpmap:0 PCMU/8000
|
||||||
|
|
||||||
|
]]>
|
||||||
|
</send>
|
||||||
|
|
||||||
|
<recv request="ACK"
|
||||||
|
rtd="true"
|
||||||
|
crlf="true">
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
<recv request="BYE">
|
||||||
|
</recv>
|
||||||
|
|
||||||
|
<send>
|
||||||
|
<![CDATA[
|
||||||
|
|
||||||
|
SIP/2.0 200 OK
|
||||||
|
[last_Via:]
|
||||||
|
[last_From:]
|
||||||
|
[last_To:]
|
||||||
|
[last_Call-ID:]
|
||||||
|
[last_CSeq:]
|
||||||
|
Contact: <sip:[local_ip]:[local_port];transport=[transport]>
|
||||||
|
Content-Length: 0
|
||||||
|
|
||||||
|
]]>
|
||||||
|
</send>
|
||||||
|
|
||||||
|
<!-- Keep the call open for a while in case the 200 is lost to be -->
|
||||||
|
<!-- able to retransmit it if we receive the BYE again. -->
|
||||||
|
<timewait milliseconds="4000"/>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- definition of the response time repartition table (unit is ms) -->
|
||||||
|
<ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/>
|
||||||
|
|
||||||
|
<!-- definition of the call length repartition table (unit is ms) -->
|
||||||
|
<CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/>
|
||||||
|
|
||||||
|
</scenario>
|
||||||
|
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
const { spawn } = require('child_process');
|
||||||
|
const debug = require('debug')('jambonz:ci');
|
||||||
|
let network;
|
||||||
|
const obj = {};
|
||||||
|
let output = '';
|
||||||
|
let idx = 1;
|
||||||
|
|
||||||
|
function clearOutput() {
|
||||||
|
output = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function addOutput(str) {
|
||||||
|
for (let i = 0; i < str.length; i++) {
|
||||||
|
if (str.charCodeAt(i) < 128) output += str.charAt(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = (networkName) => {
|
||||||
|
network = networkName ;
|
||||||
|
return obj;
|
||||||
|
};
|
||||||
|
|
||||||
|
obj.output = () => {
|
||||||
|
return output;
|
||||||
|
};
|
||||||
|
|
||||||
|
obj.sippUac = (file, regObj, bindAddress, injectionFile) => {
|
||||||
|
const cmd = 'docker';
|
||||||
|
let args = null;
|
||||||
|
if(regObj) {
|
||||||
|
args = [
|
||||||
|
'run', '--rm', '--net', `${network}`,
|
||||||
|
'-v', `${__dirname}/scenarios:/tmp/scenarios`,
|
||||||
|
'drachtio/sipp', 'sipp', `${regObj.remote_host}`, // remote host is require on auth
|
||||||
|
'-inf', `/tmp/scenarios/${regObj.data_file}`,
|
||||||
|
'-sf', `/tmp/scenarios/${file}`,
|
||||||
|
'-m', '1',
|
||||||
|
'-sleep', '250ms',
|
||||||
|
'-nostdin',
|
||||||
|
'-cid_str', `%u-%p@%s-${idx++}`,
|
||||||
|
'sbc', '-trace_msg'
|
||||||
|
];
|
||||||
|
} else if (injectionFile) {
|
||||||
|
args = [
|
||||||
|
'run', '-t', '--rm', '--net', `${network}`,
|
||||||
|
'-v', `${__dirname}/scenarios:/tmp/scenarios`,
|
||||||
|
'drachtio/sipp', 'sipp', '-sf', `/tmp/scenarios/${file}`,
|
||||||
|
'-inf', `/tmp/scenarios/${injectionFile}`,
|
||||||
|
'-m', '1',
|
||||||
|
'-sleep', '250ms',
|
||||||
|
'-nostdin',
|
||||||
|
'-cid_str', `%u-%p@%s-${idx++}`,
|
||||||
|
'172.39.0.10'];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
args = [
|
||||||
|
'run', '-t', '--rm', '--net', `${network}`,
|
||||||
|
'-v', `${__dirname}/scenarios:/tmp/scenarios`,
|
||||||
|
'drachtio/sipp', 'sipp', '-sf', `/tmp/scenarios/${file}`,
|
||||||
|
'-m', '1',
|
||||||
|
'-sleep', '250ms',
|
||||||
|
'-nostdin',
|
||||||
|
'-cid_str', `%u-%p@%s-${idx++}`,
|
||||||
|
'172.39.0.10'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bindAddress) args.splice(5, 0, '--ip', bindAddress);
|
||||||
|
|
||||||
|
clearOutput();
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const child_process = spawn(cmd, args, {stdio: ['inherit', 'pipe', 'pipe']});
|
||||||
|
|
||||||
|
child_process.on('exit', (code, signal) => {
|
||||||
|
if (code === 0) {
|
||||||
|
return resolve();
|
||||||
|
}
|
||||||
|
console.log(`sipp exited with non-zero code ${code} signal ${signal}`);
|
||||||
|
reject(code);
|
||||||
|
});
|
||||||
|
child_process.on('error', (error) => {
|
||||||
|
console.log(`error spawing child process for docker: ${args}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
child_process.stdout.on('data', (data) => {
|
||||||
|
debug(`stdout: ${data}`);
|
||||||
|
addOutput(data.toString());
|
||||||
|
});
|
||||||
|
child_process.stderr.on('data', (data) => {
|
||||||
|
debug(`stderr: ${data}`);
|
||||||
|
addOutput(data.toString());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user