Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add transfer action type #10

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,43 @@ config>
</config>
```

### Example: receive a call and transferring

```xml
<config>
<actions>
<action type="accept" label="receive_and_transfer"
account="VP_ENV_CALLEE_USERNAME"
wait_until="DISCONNECTED"
play="../voice_ref_files/reference_8000.wav"
code="200" reason="OK"
ring_duration="5"
rtp_stats
/>
<!-- note: call ends once transfer is complete -->
<action type="transfer" to_uri="12015555555@target.com"/>
</action>
</config>
```

### Example: send a call and transferring

```xml
<config>
<actions>
<action type="call" label="make_and_transfer"
transport="udp"
wait_until="CONFIRMED"
expected_cause_code="200"
caller="15147777777@noreply.com"
callee="12012222222@target.com"
/>
<!-- note: call ends once transfer is complete -->
<action type="transfer" to_uri="12015555555@target.com"/>
</actions>
</config>
```

### accept command parameters (partial list)

| Name | Type | Description |
Expand Down Expand Up @@ -276,6 +313,23 @@ export VP_ENV_PASSWORD=????????
export VP_ENV_USERNAME=username
```

### Set up environment variables from file

`voip_patrol.env`:

```bash
VP_ENV_DOMAIN=sip.example.com
VP_ENV_PROXY=192.168.0.1:5060
VP_ENV_CALLEE_EXTENSION=1000
VP_ENV_CALLEE_USERNAME=1000
VP_ENV_CALLEE_PASSWORD=password
VP_ENV_TRANSFER_TARGET=15557776666
```

```bash
export $(xargs <voip_patrol.env)
```

### Docker
```bash
voip_patrol/docker$ tree
Expand Down
89 changes: 89 additions & 0 deletions src/voip_patrol/action.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ vector<ActionParam> Action::get_params(string name) {
if (name.compare("wait") == 0) return do_wait_params;
if (name.compare("accept") == 0) return do_accept_params;
if (name.compare("alert") == 0) return do_alert_params;
if (name.compare("transfer") == 0) return do_transfer_params;
vector<ActionParam> empty_params;
return empty_params;
}
Expand Down Expand Up @@ -123,6 +124,8 @@ void Action::init_actions_params() {
do_alert_params.push_back(ActionParam("email", false, APType::apt_string));
do_alert_params.push_back(ActionParam("email_from", false, APType::apt_string));
do_alert_params.push_back(ActionParam("smtp_host", false, APType::apt_string));
// do_transfer
do_transfer_params.push_back(ActionParam("to_uri", false, APType::apt_string));
}

void Action::do_register(vector<ActionParam> &params, SipHeaderVector &x_headers) {
Expand Down Expand Up @@ -192,6 +195,13 @@ void Action::do_register(vector<ActionParam> &params, SipHeaderVector &x_headers
acc_cfg.sipConfig.proxies.push_back("sips:" + proxy);

LOG(logINFO) <<__FUNCTION__<< " SIPS URI Scheme";
} else if (acc_cfg.sipConfig.transportId == config->transport_id_udp) {
acc_cfg.idUri = "sip:" + account_name + "@" + registrar;
acc_cfg.regConfig.registrarUri = "sip:" + registrar;
if (!proxy.empty())
acc_cfg.sipConfig.proxies.push_back("sips:" + proxy);

LOG(logINFO) <<__FUNCTION__<< " SIP URI Scheme";
} else {
LOG(logINFO) <<__FUNCTION__<< " SIP URI Scheme";
acc_cfg.idUri = "sip:vp@" + registrar;
Expand Down Expand Up @@ -605,3 +615,82 @@ void Action::do_wait(vector<ActionParam> &params) {
}
}
}

void Action::do_transfer(vector<ActionParam> &params) {
bool completed = false;
int tests_running = 0;
bool status_update = true;
bool complete_all = false;

string to_uri {};

bool transferring = false;

for (auto param : params) {
if (param.name.compare("to_uri") == 0) to_uri = param.s_val;
}

if (to_uri.empty() ) {
LOG(logERROR) <<__FUNCTION__<<": missing action parameters for transfer. Must has to_uri" ;
return;
}

while (!completed) {
for (auto & account : config->accounts) {
AccountInfo acc_inf = account->getInfo();
if (account->test && account->test->state == VPT_DONE){
delete account->test;
account->test = NULL;
} else if (account->test) {
tests_running++;
}
}

for (auto & call : config->calls) {
if (call->test && call->test->state == VPT_DONE){
continue;
} else if (call->test) {
CallInfo ci = call->getInfo();
if (ci.state == PJSIP_INV_STATE_CALLING || ci.state == PJSIP_INV_STATE_EARLY) {
Test *test = call->test;
if (test->ring_duration > 0 && ci.totalDuration.sec >= test->ring_duration) {
CallOpParam prm;
if (test->reason.size() > 0) prm.reason = test->reason;
if (test->code) prm.statusCode = test->code;
call->answer(prm);
} else if (test->max_calling_duration && test->max_calling_duration <= ci.totalDuration.sec) {
LOG(logINFO) <<__FUNCTION__<<"[cancelling:call]["<<call->getId()<<"][test]["<<(ci.role==0?"CALLER":"CALLEE")<<"]["
<< ci.callIdString <<"]["<<ci.remoteUri<<"]["<<ci.stateText<<"|"<<ci.state<<"]duration["
<< ci.totalDuration.sec <<">="<<test->max_calling_duration<<"]";
CallOpParam prm(true);
try {
call->hangup(prm);
} catch (pj::Error e) {
if (e.status != 171140) LOG(logERROR) <<__FUNCTION__<<" error :" << e.status;
}
}
} else if (ci.state == PJSIP_INV_STATE_CONFIRMED) {
CallOpParam prm(true);
try {
if (to_uri.empty() ) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You have already checked it before starting the loop! Are you still needing this?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, no, I think that was just an oversight.

LOG(logERROR) <<__FUNCTION__<<": missing action parameters for to_uri" ;
return;
}

if (!transferring) {
// check transfer_type
LOG(logINFO) <<__FUNCTION__<<": doing transfer" ;
transferring = true;
call->xfer("<sip:" + to_uri + ">", prm);
}

} catch (pj::Error e) {
if (e.status != 171140) LOG(logERROR) <<__FUNCTION__<<" error :" << e.status << std::endl;
}
}
if (complete_all || call->test->state == VPT_RUN_WAIT)
tests_running++;
}
}
}
}
2 changes: 2 additions & 0 deletions src/voip_patrol/action.hh
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ class Action {
void do_wait(vector<ActionParam> &params);
void do_register(vector<ActionParam> &params, pj::SipHeaderVector &x_headers);
void do_alert(vector<ActionParam> &params);
void do_transfer(vector<ActionParam> &params);
void set_config(Config *);
Config* get_config();
private:
Expand All @@ -61,6 +62,7 @@ class Action {
vector<ActionParam> do_wait_params;
vector<ActionParam> do_accept_params;
vector<ActionParam> do_alert_params;
vector<ActionParam> do_transfer_params;
Config* config;
};

Expand Down
25 changes: 23 additions & 2 deletions src/voip_patrol/voip_patrol.cc
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,28 @@ void TestCall::onCallState(OnCallStateParam &prm) {
}
}

void TestCall::onCallTransferStatus(OnCallTransferStatusParam &prm) {
PJ_UNUSED_ARG(prm);
CallInfo ci = getInfo();

LOG(logINFO) <<__FUNCTION__<<": ["<<getId()<<"]["<<ci.remoteUri<<"]["<<ci.stateText<<"]id["<<ci.callIdString<<"]";
LOG(logINFO) <<__FUNCTION__<<": ["<<getId()<<"]["<<prm.statusCode<<"]";

if (prm.statusCode == 200) {
LOG(logINFO) <<__FUNCTION__<<": ["<<getId()<<"] transfer was successfully handled. Hanging up";
CallOpParam prm(true);
hangup(prm);
}
}

void TestCall::onCallMediaState(OnCallMediaStateParam &prm) {
PJ_UNUSED_ARG(prm);
CallInfo ci = getInfo();

LOG(logINFO) <<__FUNCTION__<<": ["<<getId()<<"]["<<ci.remoteUri<<"]["<<ci.stateText<<"]id["<<ci.callIdString<<"]";
LOG(logINFO) <<__FUNCTION__<<": ["<<getId()<<"] call is on hold";
}


/*
* TestAccount implementation
Expand Down Expand Up @@ -790,6 +812,7 @@ bool Config::process(std::string p_configFileName, std::string p_jsonResultFileN
else if ( action_type.compare("accept") == 0 ) action.do_accept(params, x_hdrs);
else if ( action_type.compare("register") == 0 ) action.do_register(params, x_hdrs);
else if ( action_type.compare("alert") == 0 ) action.do_alert(params);
else if ( action_type.compare("transfer") == 0 ) action.do_transfer(params);
}
}
}
Expand Down Expand Up @@ -1151,5 +1174,3 @@ int main(int argc, char **argv){
LOG(logINFO) <<__FUNCTION__<<": Watch completed, exiting /('l')" ;
return ret;
}


2 changes: 2 additions & 0 deletions src/voip_patrol/voip_patrol.hh
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,8 @@ class TestCall : public Call {
virtual void onCallRxOffer(OnCallTsxStateParam &prm);
virtual void onCallTsxState(OnCallTsxStateParam &prm);
virtual void onCallState(OnCallStateParam &prm);
virtual void onCallTransferStatus(OnCallTransferStatusParam &prm);
virtual void onCallMediaState(OnCallMediaStateParam &prm);
virtual void onStreamCreated(OnStreamCreatedParam &prm);
virtual void onStreamDestroyed(OnStreamDestroyedParam &prm);
virtual void onDtmfDigit(OnDtmfDigitParam &prm);
Expand Down
24 changes: 24 additions & 0 deletions xml/transfer.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<config>
<actions>
<action type="register" label="CALLEE REGISTRATION"
transport="udp"
account="VP_ENV_CALLEE_USERNAME"
username="VP_ENV_CALLEE_USERNAME"
password="VP_ENV_CALLEE_PASSWORD"
proxy="VPN_ENV_PROXY"
realm="VPN_ENV_DOMAIN"
registrar="VPN_ENV_DOMAIN"
expected_cause_code="200"
/>
<action type="wait" complete/>
<action type="accept" label="CALLEE recieves call and transfers"
account="VP_ENV_CALLEE_USERNAME"
wait_until="DISCONNECTED"
play="../voice_ref_files/reference_8000.wav"
code="200" reason="OK"
ring_duration="5"
rtp_stats
/>
<action type="transfer" to_uri="VPN_ENV_TRANSFER_TARGET@VPN_ENV_PROXY"/>
</action>
</config>