Split commands in multiple files

This commit is contained in:
Yann Diorcet 2012-05-02 17:55:16 +02:00
parent ba93e9967c
commit b429672bf8
38 changed files with 797 additions and 649 deletions

View file

@ -2,7 +2,26 @@
bin_PROGRAMS=linphone-daemon linphone-daemon-pipetest
linphone_daemon_SOURCES=daemon.cc
linphone_daemon_SOURCES=daemon.cc \
commands/answer.cc \
commands/audio-codec-disable.cc \
commands/audio-codec-enable.cc \
commands/audio-codec-get.cc \
commands/audio-codec-move.cc \
commands/audio-stream-start.cc \
commands/audio-stream-stop.cc \
commands/call.cc \
commands/call-stats.cc \
commands/call-status.cc \
commands/help.cc \
commands/pop-event.cc \
commands/ptime.cc \
commands/register.cc \
commands/register-status.cc \
commands/terminate.cc \
commands/unregister.cc \
commands/quit.cc
linphone_daemon_pipetest_SOURCES=daemon-pipetest.c

41
daemon/commands/answer.cc Normal file
View file

@ -0,0 +1,41 @@
#include "answer.h"
using namespace std;
AnswerCommand::AnswerCommand() :
DaemonCommand("answer", "answer <call id>", "Answer an incoming call.") {
}
void AnswerCommand::exec(Daemon *app, const char *args) {
LinphoneCore *lc = app->getCore();
int cid;
LinphoneCall *call;
if (sscanf(args, "%i", &cid) == 1) {
call = app->findCall(cid);
if (call == NULL) {
app->sendResponse(Response("No call with such id."));
return;
} else {
LinphoneCallState cstate = linphone_call_get_state(call);
if (cstate == LinphoneCallIncomingReceived || cstate == LinphoneCallIncomingEarlyMedia) {
if (linphone_core_accept_call(lc, call) == 0) {
app->sendResponse(Response());
return;
}
}
app->sendResponse(Response("Can't accept this call."));
return;
}
} else {
for (const MSList* elem = linphone_core_get_calls(lc); elem != NULL; elem = elem->next) {
call = (LinphoneCall*) elem->data;
LinphoneCallState cstate = linphone_call_get_state(call);
if (cstate == LinphoneCallIncomingReceived || cstate == LinphoneCallIncomingEarlyMedia) {
if (linphone_core_accept_call(lc, call) == 0) {
app->sendResponse(Response());
return;
}
}
}
}
app->sendResponse(Response("No call to accept."));
}

12
daemon/commands/answer.h Normal file
View file

@ -0,0 +1,12 @@
#ifndef COMMAND_ANSWER_H_
#define COMMAND_ANSWER_H_
#include "../daemon.h"
class AnswerCommand: public DaemonCommand {
public:
AnswerCommand();
virtual void exec(Daemon *app, const char *args);
};
#endif //COMMAND_ANSWER_H_

View file

@ -0,0 +1,27 @@
#include "audio-codec-disable.h"
using namespace std;
AudioCodecDisableCommand::AudioCodecDisableCommand() :
DaemonCommand("audio-codec-disable", "audio-codec-disable <payload type number>", "Disable an audio codec.") {
}
void AudioCodecDisableCommand::exec(Daemon *app, const char *args) {
int payload_type;
if (sscanf(args, "%d", &payload_type) == 1) {
int index = 0;
for (const MSList *node = linphone_core_get_audio_codecs(app->getCore()); node != NULL; node = ms_list_next(node)) {
PayloadType *payload = reinterpret_cast<PayloadType*>(node->data);
if (payload_type == linphone_core_get_payload_type_number(app->getCore(), payload)) {
linphone_core_enable_payload_type(app->getCore(), payload, false);
app->sendResponse(PayloadTypeResponse(app->getCore(), payload, index));
return;
}
++index;
}
app->sendResponse(Response("Audio codec not found."));
} else {
app->sendResponse(Response("Missing/Incorrect parameter(s)."));
}
}

View file

@ -0,0 +1,12 @@
#ifndef COMMAND_AUDIO_CODEC_DISABLE_H_
#define COMMAND_AUDIO_CODEC_DISABLE_H_
#include "../daemon.h"
class AudioCodecDisableCommand: public DaemonCommand {
public:
AudioCodecDisableCommand();
virtual void exec(Daemon *app, const char *args);
};
#endif //COMMAND_AUDIO_CODEC_DISABLE_H_

View file

@ -0,0 +1,25 @@
#include "audio-codec-enable.h"
using namespace std;
AudioCodecEnableCommand::AudioCodecEnableCommand() :
DaemonCommand("audio-codec-enable", "audio-codec-enable <payload type number>", "Enable an audio codec.") {
}
void AudioCodecEnableCommand::exec(Daemon *app, const char *args) {
int payload_type;
if (sscanf(args, "%d", &payload_type) == 1) {
int index = 0;
for (const MSList *node = linphone_core_get_audio_codecs(app->getCore()); node != NULL; node = ms_list_next(node)) {
PayloadType *payload = reinterpret_cast<PayloadType*>(node->data);
if (payload_type == linphone_core_get_payload_type_number(app->getCore(), payload)) {
linphone_core_enable_payload_type(app->getCore(), payload, true);
app->sendResponse(PayloadTypeResponse(app->getCore(), payload, index));
return;
}
++index;
}
app->sendResponse(Response("Audio codec not found."));
} else {
app->sendResponse(Response("Missing/Incorrect parameter(s)."));
}
}

View file

@ -0,0 +1,12 @@
#ifndef COMMAND_AUDIO_CODEC_ENABLE_H_
#define COMMAND_AUDIO_CODEC_ENABLE_H_
#include "../daemon.h"
class AudioCodecEnableCommand: public DaemonCommand {
public:
AudioCodecEnableCommand();
virtual void exec(Daemon *app, const char *args);
};
#endif //COMMAND_AUDIO_CODEC_ENABLE_H_

View file

@ -0,0 +1,33 @@
#include "audio-codec-get.h"
#include <sstream>
using namespace std;
AudioCodecGetCommand::AudioCodecGetCommand() :
DaemonCommand("audio-codec-get", "audio-codec-get <payload type number>", "Get an audio codec if codec-mime is defined, otherwise return the audio codec list.") {
}
void AudioCodecGetCommand::exec(Daemon *app, const char *args) {
int payload_type;
bool list = sscanf(args, "%d", &payload_type) != 1;
bool find = list;
int index = 0;
ostringstream ostr;
for (const MSList *node = linphone_core_get_audio_codecs(app->getCore()); node != NULL; node = ms_list_next(node)) {
PayloadType *payload = reinterpret_cast<PayloadType*>(node->data);
if (list) {
ostr << PayloadTypeResponse(app->getCore(), payload, index).getBody() << "\n";
} else if (payload_type == linphone_core_get_payload_type_number(app->getCore(), payload)) {
ostr << PayloadTypeResponse(app->getCore(), payload, index).getBody();
find = true;
break;
}
++index;
}
if (!find) {
app->sendResponse(Response("Audio codec not found."));
} else {
app->sendResponse(Response(ostr.str().c_str(), Response::Ok));
}
}

View file

@ -0,0 +1,12 @@
#ifndef COMMAND_AUDIO_CODEC_GET_H_
#define COMMAND_AUDIO_CODEC_GET_H_
#include "../daemon.h"
class AudioCodecGetCommand: public DaemonCommand {
public:
AudioCodecGetCommand();
virtual void exec(Daemon *app, const char *args);
};
#endif //COMMAND_AUDIO_CODEC_GET_H_

View file

@ -0,0 +1,49 @@
#include "audio-codec-move.h"
#include <sstream>
using namespace std;
AudioCodecMoveCommand::AudioCodecMoveCommand() :
DaemonCommand("audio-codec-move", "audio-codec-move <payload type number> <index>", "Move a codec to the an index.") {
}
void AudioCodecMoveCommand::exec(Daemon *app, const char *args) {
int payload_type;
int index;
if (sscanf(args, "%d %d", &payload_type, &index) == 2 && index >= 0) {
PayloadType *selected_payload = NULL;
for (const MSList *node = linphone_core_get_audio_codecs(app->getCore()); node != NULL; node = ms_list_next(node)) {
PayloadType *payload = reinterpret_cast<PayloadType*>(node->data);
if (payload_type == linphone_core_get_payload_type_number(app->getCore(), payload)) {
selected_payload = payload;
break;
}
}
if (selected_payload == NULL) {
app->sendResponse(Response("Audio codec not found."));
return;
}
int i = 0;
MSList *mslist = NULL;
for (const MSList *node = linphone_core_get_audio_codecs(app->getCore()); node != NULL; node = ms_list_next(node)) {
PayloadType *payload = reinterpret_cast<PayloadType*>(node->data);
if (i == index) {
mslist = ms_list_append(mslist, selected_payload);
++i;
}
if (selected_payload != payload) {
mslist = ms_list_append(mslist, payload);
++i;
}
}
if (i <= index) {
index = i;
mslist = ms_list_append(mslist, selected_payload);
}
linphone_core_set_audio_codecs(app->getCore(), mslist);
app->sendResponse(PayloadTypeResponse(app->getCore(), selected_payload, index));
} else {
app->sendResponse(Response("Missing/Incorrect parameter(s)."));
}
}

View file

@ -0,0 +1,12 @@
#ifndef COMMAND_AUDIO_CODEC_MOVE_H_
#define COMMAND_AUDIO_CODEC_MOVE_H_
#include "../daemon.h"
class AudioCodecMoveCommand: public DaemonCommand {
public:
AudioCodecMoveCommand();
virtual void exec(Daemon *app, const char *args);
};
#endif //COMMAND_AUDIO_CODEC_MOVE_H_

View file

@ -0,0 +1,32 @@
#include "audio-stream-start.h"
#include <sstream>
using namespace std;
AudioStreamStartCommand::AudioStreamStartCommand() :
DaemonCommand("audio-stream-start", "audio-stream-start <remote ip> <remote port> <payload type number>", "Start an audio stream.") {
}
void AudioStreamStartCommand::exec(Daemon *app, const char *args) {
char addr[256];
int port;
int payload_type;
if (sscanf(args, "%255s %d %d", addr, &port, &payload_type) == 3) {
int local_port = linphone_core_get_audio_port(app->getCore());
const int jitt = linphone_core_get_audio_jittcomp(app->getCore());
const bool_t echo_canceller = linphone_core_echo_cancellation_enabled(app->getCore());
MSSndCardManager *manager = ms_snd_card_manager_get();
MSSndCard *capture_card = ms_snd_card_manager_get_card(manager, linphone_core_get_capture_device(app->getCore()));
MSSndCard *play_card = ms_snd_card_manager_get_card(manager, linphone_core_get_playback_device(app->getCore()));
AudioStream *stream = audio_stream_new(local_port, false);
if (audio_stream_start_now(stream, &av_profile, addr, port, port + 1, payload_type, jitt, play_card, capture_card, echo_canceller) != 0) {
app->sendResponse(Response("Error during audio stream creation."));
}
ostringstream ostr;
ostr << "Id: " << app->setAudioStreamId(stream) << "\n";
app->sendResponse(Response(ostr.str().c_str(), Response::Ok));
} else {
app->sendResponse(Response("Missing/Incorrect parameter(s)."));
}
}

View file

@ -0,0 +1,12 @@
#ifndef COMMAND_AUDIO_STREAM_START_H_
#define COMMAND_AUDIO_STREAM_START_H_
#include "../daemon.h"
class AudioStreamStartCommand: public DaemonCommand {
public:
AudioStreamStartCommand();
virtual void exec(Daemon *app, const char *args);
};
#endif //COMMAND_AUDIO_STREAM_START_H_

View file

@ -0,0 +1,21 @@
#include "audio-stream-stop.h"
using namespace std;
AudioStreamStopCommand::AudioStreamStopCommand() :
DaemonCommand("audio-stream-stop", "audio-stream-stop <audio stream id>", "Stop an audio stream.") {
}
void AudioStreamStopCommand::exec(Daemon *app, const char *args) {
int id;
if (sscanf(args, "%d", &id) == 1) {
AudioStream *stream = app->findAudioStream(id);
if (stream == NULL) {
app->sendResponse(Response("No Audio Stream with such id."));
return;
}
audio_stream_stop(stream);
app->sendResponse(Response());
} else {
app->sendResponse(Response("Missing/Incorrect parameter(s)."));
}
}

View file

@ -0,0 +1,12 @@
#ifndef COMMAND_AUDIO_STREAM_STOP_H_
#define COMMAND_AUDIO_STREAM_STOP_H_
#include "../daemon.h"
class AudioStreamStopCommand: public DaemonCommand {
public:
AudioStreamStopCommand();
virtual void exec(Daemon *app, const char *args);
};
#endif //COMMAND_AUDIO_STREAM_STOP_H_

View file

@ -0,0 +1,48 @@
#include "call-stats.h"
#include <sstream>
using namespace std;
CallStatsCommand::CallStatsCommand() :
DaemonCommand("call-stats", "call-stats <call id>", "Return all stats of a call.") {
}
void CallStatsCommand::exec(Daemon *app, const char *args) {
LinphoneCore *lc = app->getCore();
int cid;
LinphoneCall *call = NULL;
if (sscanf(args, "%i", &cid) == 1) {
call = app->findCall(cid);
if (call == NULL) {
app->sendResponse(Response("No call with such id."));
return;
}
} else {
call = linphone_core_get_current_call(lc);
if (call == NULL) {
app->sendResponse(Response("No current call available."));
return;
}
}
LinphoneCallState call_state = LinphoneCallIdle;
call_state = linphone_call_get_state(call);
const LinphoneCallParams *callParams = linphone_call_get_current_params(call);
const PayloadType *audioCodec = linphone_call_params_get_used_audio_codec(callParams);
const PayloadType *videoCodec = linphone_call_params_get_used_video_codec(callParams);
ostringstream ostr;
ostr << linphone_call_state_to_string(call_state) << "\n";
switch (call_state) {
case LinphoneCallStreamsRunning:
case LinphoneCallConnected:
if (audioCodec != NULL)
ostr << PayloadTypeResponse(app->getCore(), audioCodec, -1, "Audio-", false).getBody() << "\n";
if (videoCodec != NULL)
ostr << PayloadTypeResponse(app->getCore(), videoCodec, -1, "Audio-", false).getBody() << "\n";
break;
default:
break;
}
app->sendResponse(Response(ostr.str().c_str(), Response::Ok));
}

View file

@ -0,0 +1,12 @@
#ifndef COMMAND_CALL_STATS_H_
#define COMMAND_CALL_STATS_H_
#include "../daemon.h"
class CallStatsCommand: public DaemonCommand {
public:
CallStatsCommand();
virtual void exec(Daemon *app, const char *args);
};
#endif //COMMAND_CALL_STATS_H_

View file

@ -0,0 +1,57 @@
#include "call-status.h"
#include <sstream>
using namespace std;
CallStatusCommand::CallStatusCommand() :
DaemonCommand("call-status", "call-status <call id>", "Return status of a call.") {
}
void CallStatusCommand::exec(Daemon *app, const char *args) {
LinphoneCore *lc = app->getCore();
int cid;
LinphoneCall *call = NULL;
if (sscanf(args, "%i", &cid) == 1) {
call = app->findCall(cid);
if (call == NULL) {
app->sendResponse(Response("No call with such id."));
return;
}
} else {
call = linphone_core_get_current_call(lc);
if (call == NULL) {
app->sendResponse(Response("No current call available."));
return;
}
}
LinphoneCallState call_state = LinphoneCallIdle;
call_state = linphone_call_get_state(call);
const LinphoneAddress *remoteAddress = linphone_call_get_remote_address(call);
ostringstream ostr;
ostr << linphone_call_state_to_string(call_state) << "\n";
switch (call_state) {
case LinphoneCallOutgoingInit:
case LinphoneCallOutgoingProgress:
case LinphoneCallOutgoingRinging:
case LinphoneCallPaused:
case LinphoneCallStreamsRunning:
case LinphoneCallConnected:
case LinphoneCallIncomingReceived:
ostr << "From: " << linphone_address_as_string(remoteAddress) << "\n";
break;
default:
break;
}
switch (call_state) {
case LinphoneCallStreamsRunning:
case LinphoneCallConnected:
ostr << "Direction: " << ((linphone_call_get_dir(call) == LinphoneCallOutgoing) ? "out" : "in") << "\n";
ostr << "Duration: " << linphone_call_get_duration(call) << "\n";
break;
default:
break;
}
app->sendResponse(Response(ostr.str().c_str(), Response::Ok));
}

View file

@ -0,0 +1,12 @@
#ifndef COMMAND_CALL_STATUS_H_
#define COMMAND_CALL_STATUS_H_
#include "../daemon.h"
class CallStatusCommand: public DaemonCommand {
public:
CallStatusCommand();
virtual void exec(Daemon *app, const char *args);
};
#endif //COMMAND_CALL_STATUS_H_

23
daemon/commands/call.cc Normal file
View file

@ -0,0 +1,23 @@
#include "call.h"
#include <sstream>
using namespace std;
CallCommand::CallCommand() :
DaemonCommand("call", "call <sip address>", "Place a call.") {
}
void CallCommand::exec(Daemon *app, const char *args) {
LinphoneCall *call;
call = linphone_core_invite(app->getCore(), args);
if (call == NULL) {
app->sendResponse(Response("Call creation failed."));
} else {
Response resp;
ostringstream ostr;
ostr << "Id: " << app->setCallId(call) << "\n";
resp.setBody(ostr.str().c_str());
app->sendResponse(resp);
}
}

12
daemon/commands/call.h Normal file
View file

@ -0,0 +1,12 @@
#ifndef COMMAND_CALL_H_
#define COMMAND_CALL_H_
#include "../daemon.h"
class CallCommand: public DaemonCommand {
public:
CallCommand();
virtual void exec(Daemon *app, const char *args);
};
#endif //COMMAND_CALL_H_

19
daemon/commands/help.cc Normal file
View file

@ -0,0 +1,19 @@
#include "help.h"
using namespace std;
HelpCommand::HelpCommand() :
DaemonCommand("help", "help", "Show available commands.") {
}
void HelpCommand::exec(Daemon *app, const char *args) {
char str[4096] = { 0 };
int written = 0;
list<DaemonCommand*>::const_iterator it;
const list<DaemonCommand*> &l = app->getCommandList();
for (it = l.begin(); it != l.end(); ++it) {
written += snprintf(str + written, sizeof(str) - written, "%s\t%s\n", (*it)->getProto().c_str(), (*it)->getHelp().c_str());
}
Response resp;
resp.setBody(str);
app->sendResponse(resp);
}

12
daemon/commands/help.h Normal file
View file

@ -0,0 +1,12 @@
#ifndef COMMAND_HELP_H_
#define COMMAND_HELP_H_
#include "../daemon.h"
class HelpCommand: public DaemonCommand {
public:
HelpCommand();
virtual void exec(Daemon *app, const char *args);
};
#endif //COMMAND_HELP_H_

View file

@ -0,0 +1,10 @@
#include "pop-event.h"
using namespace std;
PopEventCommand::PopEventCommand() :
DaemonCommand("pop-event", "pop-event", "Pop an event from event queue and display it.") {
}
void PopEventCommand::exec(Daemon *app, const char *args) {
app->pullEvent();
}

View file

@ -0,0 +1,12 @@
#ifndef COMMAND_POP_EVENT_H_
#define COMMAND_POP_EVENT_H_
#include "../daemon.h"
class PopEventCommand: public DaemonCommand {
public:
PopEventCommand();
virtual void exec(Daemon *app, const char *args);
};
#endif //COMMAND_POP_EVENT_H_

27
daemon/commands/ptime.cc Normal file
View file

@ -0,0 +1,27 @@
#include "ptime.h"
#include <sstream>
using namespace std;
PtimeCommand::PtimeCommand() :
DaemonCommand("ptime", "ptime <ms>", "Set the if ms is defined, otherwise return the ptime.") {
}
void PtimeCommand::exec(Daemon *app, const char *args) {
int ms;
int ret = sscanf(args, "%d", &ms);
if (ret <= 0) {
ostringstream ostr;
ms = linphone_core_get_upload_ptime(app->getCore());
ostr << "Ptime: " << ms << "\n";
app->sendResponse(Response(ostr.str().c_str(), Response::Ok));
} else if (ret == 1) {
ostringstream ostr;
linphone_core_set_upload_ptime(app->getCore(), ms);
ms = linphone_core_get_upload_ptime(app->getCore());
ostr << "Ptime: " << ms << "\n";
app->sendResponse(Response(ostr.str().c_str(), Response::Ok));
} else {
app->sendResponse(Response("Missing/Incorrect parameter(s)."));
}
}

12
daemon/commands/ptime.h Normal file
View file

@ -0,0 +1,12 @@
#ifndef COMMAND_PTIME_H_
#define COMMAND_PTIME_H_
#include "../daemon.h"
class PtimeCommand: public DaemonCommand {
public:
PtimeCommand();
virtual void exec(Daemon *app, const char *args);
};
#endif //COMMAND_PTIME_H_

14
daemon/commands/quit.cc Normal file
View file

@ -0,0 +1,14 @@
#include "quit.h"
#include <sstream>
using namespace std;
QuitCommand::QuitCommand() :
DaemonCommand("quit", "quit", "Quit the application.") {
}
void QuitCommand::exec(Daemon *app, const char *args) {
app->quit();
app->sendResponse(Response());
}

12
daemon/commands/quit.h Normal file
View file

@ -0,0 +1,12 @@
#ifndef COMMAND_QUIT_H_
#define COMMAND_QUIT_H_
#include "../daemon.h"
class QuitCommand: public DaemonCommand {
public:
QuitCommand();
virtual void exec(Daemon *app, const char *args);
};
#endif //COMMAND_QUIT_H_

View file

@ -0,0 +1,23 @@
#include "register-status.h"
using namespace std;
RegisterStatusCommand::RegisterStatusCommand() :
DaemonCommand("register-status", "register-status <register id>", "Return status of a register.") {
}
void RegisterStatusCommand::exec(Daemon *app, const char *args) {
LinphoneProxyConfig *cfg = NULL;
int pid;
if (sscanf(args, "%i", &pid) == 1) {
cfg = app->findProxy(pid);
if (cfg == NULL) {
app->sendResponse(Response("No register with such id."));
return;
}
} else {
app->sendResponse(Response("Missing/Incorrect parameter(s)."));
return;
}
app->sendResponse(Response(linphone_registration_state_to_string(linphone_proxy_config_get_state(cfg)), Response::Ok));
}

View file

@ -0,0 +1,12 @@
#ifndef COMMAND_REGISTER_STATUS_H_
#define COMMAND_REGISTER_STATUS_H_
#include "../daemon.h"
class RegisterStatusCommand: public DaemonCommand {
public:
RegisterStatusCommand();
virtual void exec(Daemon *app, const char *args);
};
#endif //COMMAND_REGISTER_STATUS_H_

View file

@ -0,0 +1,35 @@
#include "register.h"
#include <sstream>
using namespace std;
RegisterCommand::RegisterCommand() :
DaemonCommand("register", "register <identity> <proxy-address> <password>", "Register the daemon to a SIP proxy.") {
}
void RegisterCommand::exec(Daemon *app, const char *args) {
LinphoneCore *lc = app->getCore();
char proxy[256] = { 0 }, identity[128] = { 0 }, password[64] = { 0 };
if (sscanf(args, "%255s %127s %63s", identity, proxy, password) >= 2) {
LinphoneProxyConfig *cfg = linphone_proxy_config_new();
if (password[0] != '\0') {
LinphoneAddress *from = linphone_address_new(identity);
if (from != NULL) {
LinphoneAuthInfo *info = linphone_auth_info_new(linphone_address_get_username(from), NULL, password, NULL, NULL); /*create authentication structure from identity*/
linphone_core_add_auth_info(lc, info); /*add authentication info to LinphoneCore*/
linphone_address_destroy(from);
linphone_auth_info_destroy(info);
}
}
linphone_proxy_config_set_identity(cfg, identity);
linphone_proxy_config_set_server_addr(cfg, proxy);
linphone_proxy_config_enable_register(cfg, TRUE);
app->setProxyId(cfg);
ostringstream ostr;
ostr << "Id: " << Daemon::getProxyId(cfg) << "\n";
linphone_core_add_proxy_config(lc, cfg);
app->sendResponse(Response(ostr.str().c_str(), Response::Ok));
} else {
app->sendResponse(Response("Missing/Incorrect parameter(s)."));
}
}

View file

@ -0,0 +1,12 @@
#ifndef COMMAND_REGISTER_H_
#define COMMAND_REGISTER_H_
#include "../daemon.h"
class RegisterCommand: public DaemonCommand {
public:
RegisterCommand();
virtual void exec(Daemon *app, const char *args);
};
#endif //COMMAND_REGISTER_H_

View file

@ -0,0 +1,30 @@
#include "terminate.h"
using namespace std;
TerminateCommand::TerminateCommand() :
DaemonCommand("terminate", "terminate <call id>", "Terminate a call.") {
}
void TerminateCommand::exec(Daemon *app, const char *args) {
LinphoneCall *call = NULL;
int cid;
const MSList *elem;
if (sscanf(args, "%i", &cid) == 1) {
call = app->findCall(cid);
if (call == NULL) {
app->sendResponse(Response("No call with such id."));
return;
}
} else {
elem = linphone_core_get_calls(app->getCore());
if (elem != NULL && elem->next == NULL) {
call = (LinphoneCall*) elem->data;
}
}
if (call == NULL) {
app->sendResponse(Response("No active call."));
return;
}
linphone_core_terminate_call(app->getCore(), call);
app->sendResponse(Response());
}

View file

@ -0,0 +1,12 @@
#ifndef COMMAND_TERMINATE_H_
#define COMMAND_TERMINATE_H_
#include "../daemon.h"
class TerminateCommand: public DaemonCommand {
public:
TerminateCommand();
virtual void exec(Daemon *app, const char *args);
};
#endif //COMMAND_TERMINATE_H_

View file

@ -0,0 +1,24 @@
#include "unregister.h"
using namespace std;
UnregisterCommand::UnregisterCommand() :
DaemonCommand("unregister", "unregister <register_id>", "Unregister the daemon from proxy.") {
}
void UnregisterCommand::exec(Daemon *app, const char *args) {
LinphoneCore *lc = app->getCore();
LinphoneProxyConfig *cfg = NULL;
int pid;
if (sscanf(args, "%i", &pid) == 1) {
cfg = app->findProxy(pid);
if (cfg == NULL) {
app->sendResponse(Response("No register with such id."));
return;
}
} else {
app->sendResponse(Response("Missing/Incorrect parameter(s)."));
return;
}
linphone_core_remove_proxy_config(lc, cfg);
app->sendResponse(Response());
}

View file

@ -0,0 +1,12 @@
#ifndef COMMAND_UNREGISTER_H_
#define COMMAND_UNREGISTER_H_
#include "../daemon.h"
class UnregisterCommand: public DaemonCommand {
public:
UnregisterCommand();
virtual void exec(Daemon *app, const char *args);
};
#endif //COMMAND_UNREGISTER_H_

View file

@ -1,659 +1,34 @@
#include <linphonecore.h>
#include <mediastreamer2/mediastream.h>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <readline/readline.h>
#include <readline/history.h>
#include <poll.h>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <list>
#include <map>
#include <queue>
#include "daemon.h"
#include "commands/answer.h"
#include "commands/audio-codec-get.h"
#include "commands/audio-codec-move.h"
#include "commands/audio-codec-enable.h"
#include "commands/audio-codec-disable.h"
#include "commands/audio-stream-start.h"
#include "commands/audio-stream-stop.h"
#include "commands/call.h"
#include "commands/call-stats.h"
#include "commands/call-status.h"
#include "commands/help.h"
#include "commands/pop-event.h"
#include "commands/ptime.h"
#include "commands/register.h"
#include "commands/register-status.h"
#include "commands/terminate.h"
#include "commands/unregister.h"
#include "commands/quit.h"
using namespace std;
class Daemon;
class DaemonCommand {
public:
virtual void exec(Daemon *app, const char *args)=0;
bool matches(const char *name) const;
const std::string &getProto() const {
return mProto;
}
const std::string &getHelp() const {
return mHelp;
}
protected:
DaemonCommand(const char *name, const char *proto, const char *help);
const std::string mName;
const std::string mProto;
const std::string mHelp;
};
class Response {
public:
enum Status {
Ok, Error
};
virtual ~Response() {
}
Response() :
mStatus(Ok) {
}
Response(const char *msg, Status status = Error) :
mStatus(status) {
if (status == Ok) {
mBody = msg;
} else {
mReason = msg;
}
}
void setStatus(Status st) {
mStatus = st;
}
void setReason(const char *reason) {
mReason = reason;
}
void setBody(const char *body) {
mBody = body;
}
const std::string &getBody() const {
return mBody;
}
virtual int toBuf(char *dst, int dstlen) const {
int i = 0;
i += snprintf(dst + i, dstlen - i, "Status: %s\n", mStatus == Ok ? "Ok" : "Error");
if (mReason.size() > 0) {
i += snprintf(dst + i, dstlen - i, "Reason: %s\n", mReason.c_str());
}
if (mBody.size() > 0) {
i += snprintf(dst + i, dstlen - i, "\n%s\n", mBody.c_str());
}
return i;
}
private:
Status mStatus;
string mReason;
string mBody;
};
class EventResponse: public Response {
public:
EventResponse(LinphoneCall *call, LinphoneCallState state);
private:
};
class PayloadTypeResponse: public Response {
public:
PayloadTypeResponse(LinphoneCore *core, const PayloadType *payloadType, int index = -1, const string &prefix = string(), bool enabled_status = true);
private:
};
class Daemon {
friend class DaemonCommand;
public:
typedef Response::Status Status;
Daemon(const char *config_path, const char *factory_config_path, const char *log_file, const char *pipe_name, bool display_video, bool capture_video);
~Daemon();
int run();
void quit();
void sendResponse(const Response &resp);
LinphoneCore *getCore();
const list<DaemonCommand*> &getCommandList() const;
LinphoneCall *findCall(int id);
LinphoneProxyConfig *findProxy(int id);
AudioStream *findAudioStream(int id);
bool pullEvent();
static int getCallId(LinphoneCall *call);
int setCallId(LinphoneCall *call);
static int getProxyId(LinphoneProxyConfig *proxy);
int setProxyId(LinphoneProxyConfig *proxy);
int setAudioStreamId(AudioStream *audio_stream);
private:
static void callStateChanged(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState state, const char *msg);
static int readlineHook();
void callStateChanged(LinphoneCall *call, LinphoneCallState state, const char *msg);
void execCommand(const char *cl);
void initReadline();
char *readPipe(char *buffer, int buflen);
void iterate();
void initCommands();
void uninitCommands();
LinphoneCore *mLc;
std::list<DaemonCommand*> mCommands;
queue<EventResponse*> mEventQueue;
int mServerFd;
int mChildFd;
string mHistfile;
bool mRunning;
FILE *mLogFile;
static Daemon *sZis;
static int sCallIds;
static int sProxyIds;
static int sAudioStreamIds;
static const int sLineSize = 512;
std::map<int, AudioStream*> mAudioStreams;
};
class CallCommand: public DaemonCommand {
public:
CallCommand() :
DaemonCommand("call", "call <sip address>", "Place a call.") {
}
virtual void exec(Daemon *app, const char *args) {
LinphoneCall *call;
call = linphone_core_invite(app->getCore(), args);
if (call == NULL) {
app->sendResponse(Response("Call creation failed."));
} else {
Response resp;
ostringstream ostr;
ostr << "Id: " << app->setCallId(call) << "\n";
resp.setBody(ostr.str().c_str());
app->sendResponse(resp);
}
}
};
class TerminateCommand: public DaemonCommand {
public:
TerminateCommand() :
DaemonCommand("terminate", "terminate <call id>", "Terminate a call.") {
}
virtual void exec(Daemon *app, const char *args) {
LinphoneCall *call = NULL;
int cid;
const MSList *elem;
if (sscanf(args, "%i", &cid) == 1) {
call = app->findCall(cid);
if (call == NULL) {
app->sendResponse(Response("No call with such id."));
return;
}
} else {
elem = linphone_core_get_calls(app->getCore());
if (elem != NULL && elem->next == NULL) {
call = (LinphoneCall*) elem->data;
}
}
if (call == NULL) {
app->sendResponse(Response("No active call."));
return;
}
linphone_core_terminate_call(app->getCore(), call);
app->sendResponse(Response());
}
};
class QuitCommand: public DaemonCommand {
public:
QuitCommand() :
DaemonCommand("quit", "quit", "Quit the application.") {
}
virtual void exec(Daemon *app, const char *args) {
app->quit();
app->sendResponse(Response());
}
};
class HelpCommand: public DaemonCommand {
public:
HelpCommand() :
DaemonCommand("help", "help", "Show available commands.") {
}
virtual void exec(Daemon *app, const char *args) {
char str[4096] = { 0 };
int written = 0;
list<DaemonCommand*>::const_iterator it;
const list<DaemonCommand*> &l = app->getCommandList();
for (it = l.begin(); it != l.end(); ++it) {
written += snprintf(str + written, sizeof(str) - written, "%s\t%s\n", (*it)->getProto().c_str(), (*it)->getHelp().c_str());
}
Response resp;
resp.setBody(str);
app->sendResponse(resp);
}
};
class RegisterCommand: public DaemonCommand {
public:
RegisterCommand() :
DaemonCommand("register", "register <identity> <proxy-address> <password>", "Register the daemon to a SIP proxy.") {
}
virtual void exec(Daemon *app, const char *args) {
LinphoneCore *lc = app->getCore();
char proxy[256] = { 0 }, identity[128] = { 0 }, password[64] = { 0 };
if (sscanf(args, "%255s %127s %63s", identity, proxy, password) >= 2) {
LinphoneProxyConfig *cfg = linphone_proxy_config_new();
if (password[0] != '\0') {
LinphoneAddress *from = linphone_address_new(identity);
if (from != NULL) {
LinphoneAuthInfo *info = linphone_auth_info_new(linphone_address_get_username(from), NULL, password, NULL, NULL); /*create authentication structure from identity*/
linphone_core_add_auth_info(lc, info); /*add authentication info to LinphoneCore*/
linphone_address_destroy(from);
linphone_auth_info_destroy(info);
}
}
linphone_proxy_config_set_identity(cfg, identity);
linphone_proxy_config_set_server_addr(cfg, proxy);
linphone_proxy_config_enable_register(cfg, TRUE);
app->setProxyId(cfg);
ostringstream ostr;
ostr << "Id: " << Daemon::getProxyId(cfg) << "\n";
linphone_core_add_proxy_config(lc, cfg);
app->sendResponse(Response(ostr.str().c_str(), Response::Ok));
} else {
app->sendResponse(Response("Missing/Incorrect parameter(s)."));
}
}
};
class UnregisterCommand: public DaemonCommand {
public:
UnregisterCommand() :
DaemonCommand("unregister", "unregister <register_id>", "Unregister the daemon from proxy.") {
}
virtual void exec(Daemon *app, const char *args) {
LinphoneCore *lc = app->getCore();
LinphoneProxyConfig *cfg = NULL;
int pid;
if (sscanf(args, "%i", &pid) == 1) {
cfg = app->findProxy(pid);
if (cfg == NULL) {
app->sendResponse(Response("No register with such id."));
return;
}
} else {
app->sendResponse(Response("Missing/Incorrect parameter(s)."));
return;
}
linphone_core_remove_proxy_config(lc, cfg);
app->sendResponse(Response());
}
};
class PopEventCommand: public DaemonCommand {
public:
PopEventCommand() :
DaemonCommand("pop-event", "pop-event", "Pop an event from event queue and display it.") {
}
virtual void exec(Daemon *app, const char *args) {
app->pullEvent();
}
};
class AudioStreamStartCommand: public DaemonCommand {
public:
AudioStreamStartCommand() :
DaemonCommand("audio-stream-start", "audio-stream-start <remote ip> <remote port> <payload type number>", "Start an audio stream.") {
}
virtual void exec(Daemon *app, const char *args) {
char addr[256];
int port;
int payload_type;
if (sscanf(args, "%255s %d %d", addr, &port, &payload_type) == 3) {
int local_port = linphone_core_get_audio_port(app->getCore());
const int jitt = linphone_core_get_audio_jittcomp(app->getCore());
const bool_t echo_canceller = linphone_core_echo_cancellation_enabled(app->getCore());
MSSndCardManager *manager = ms_snd_card_manager_get();
MSSndCard *capture_card = ms_snd_card_manager_get_card(manager, linphone_core_get_capture_device(app->getCore()));
MSSndCard *play_card = ms_snd_card_manager_get_card(manager, linphone_core_get_playback_device(app->getCore()));
AudioStream *stream = audio_stream_new(local_port, false);
if (audio_stream_start_now(stream, &av_profile, addr, port, port + 1, payload_type, jitt, play_card, capture_card, echo_canceller) != 0) {
app->sendResponse(Response("Error during audio stream creation."));
}
ostringstream ostr;
ostr << "Id: " << app->setAudioStreamId(stream) << "\n";
app->sendResponse(Response(ostr.str().c_str(), Response::Ok));
} else {
app->sendResponse(Response("Missing/Incorrect parameter(s)."));
}
}
};
class AudioStreamStopCommand: public DaemonCommand {
public:
AudioStreamStopCommand() :
DaemonCommand("audio-stream-stop", "audio-stream-stop <audio stream id>", "Stop an audio stream.") {
}
virtual void exec(Daemon *app, const char *args) {
int id;
if (sscanf(args, "%d", &id) == 1) {
AudioStream *stream = app->findAudioStream(id);
if (stream == NULL) {
app->sendResponse(Response("No Audio Stream with such id."));
return;
}
audio_stream_stop(stream);
app->sendResponse(Response());
} else {
app->sendResponse(Response("Missing/Incorrect parameter(s)."));
}
}
};
class RegisterStatusCommand: public DaemonCommand {
public:
RegisterStatusCommand() :
DaemonCommand("register-status", "register-status <register id>", "Return status of a register.") {
}
virtual void exec(Daemon *app, const char *args) {
LinphoneProxyConfig *cfg = NULL;
int pid;
if (sscanf(args, "%i", &pid) == 1) {
cfg = app->findProxy(pid);
if (cfg == NULL) {
app->sendResponse(Response("No register with such id."));
return;
}
} else {
app->sendResponse(Response("Missing/Incorrect parameter(s)."));
return;
}
app->sendResponse(Response(linphone_registration_state_to_string(linphone_proxy_config_get_state(cfg)), Response::Ok));
}
};
class CallStatsCommand: public DaemonCommand {
public:
CallStatsCommand() :
DaemonCommand("call-stats", "call-stats <call id>", "Return all stats of a call.") {
}
virtual void exec(Daemon *app, const char *args) {
LinphoneCore *lc = app->getCore();
int cid;
LinphoneCall *call = NULL;
if (sscanf(args, "%i", &cid) == 1) {
call = app->findCall(cid);
if (call == NULL) {
app->sendResponse(Response("No call with such id."));
return;
}
} else {
call = linphone_core_get_current_call(lc);
if (call == NULL) {
app->sendResponse(Response("No current call available."));
return;
}
}
LinphoneCallState call_state = LinphoneCallIdle;
call_state = linphone_call_get_state(call);
const LinphoneCallParams *callParams = linphone_call_get_current_params(call);
const PayloadType *audioCodec = linphone_call_params_get_used_audio_codec(callParams);
const PayloadType *videoCodec = linphone_call_params_get_used_video_codec(callParams);
ostringstream ostr;
ostr << linphone_call_state_to_string(call_state) << "\n";
switch (call_state) {
case LinphoneCallStreamsRunning:
case LinphoneCallConnected:
if (audioCodec != NULL)
ostr << PayloadTypeResponse(app->getCore(), audioCodec, -1, "Audio-", false).getBody() << "\n";
if (videoCodec != NULL)
ostr << PayloadTypeResponse(app->getCore(), videoCodec, -1, "Audio-", false).getBody() << "\n";
break;
default:
break;
}
app->sendResponse(Response(ostr.str().c_str(), Response::Ok));
}
};
class CallStatusCommand: public DaemonCommand {
public:
CallStatusCommand() :
DaemonCommand("call-status", "call-status <call id>", "Return status of a call.") {
}
virtual void exec(Daemon *app, const char *args) {
LinphoneCore *lc = app->getCore();
int cid;
LinphoneCall *call = NULL;
if (sscanf(args, "%i", &cid) == 1) {
call = app->findCall(cid);
if (call == NULL) {
app->sendResponse(Response("No call with such id."));
return;
}
} else {
call = linphone_core_get_current_call(lc);
if (call == NULL) {
app->sendResponse(Response("No current call available."));
return;
}
}
LinphoneCallState call_state = LinphoneCallIdle;
call_state = linphone_call_get_state(call);
const LinphoneAddress *remoteAddress = linphone_call_get_remote_address(call);
ostringstream ostr;
ostr << linphone_call_state_to_string(call_state) << "\n";
switch (call_state) {
case LinphoneCallOutgoingInit:
case LinphoneCallOutgoingProgress:
case LinphoneCallOutgoingRinging:
case LinphoneCallPaused:
case LinphoneCallStreamsRunning:
case LinphoneCallConnected:
case LinphoneCallIncomingReceived:
ostr << "From: " << linphone_address_as_string(remoteAddress) << "\n";
break;
default:
break;
}
switch (call_state) {
case LinphoneCallStreamsRunning:
case LinphoneCallConnected:
ostr << "Direction: " << ((linphone_call_get_dir(call) == LinphoneCallOutgoing) ? "out" : "in") << "\n";
ostr << "Duration: " << linphone_call_get_duration(call) << "\n";
break;
default:
break;
}
app->sendResponse(Response(ostr.str().c_str(), Response::Ok));
}
};
class PtimeCommand: public DaemonCommand {
public:
PtimeCommand() :
DaemonCommand("ptime", "ptime <ms>", "Set the if ms is defined, otherwise return the ptime.") {
}
virtual void exec(Daemon *app, const char *args) {
int ms;
int ret = sscanf(args, "%d", &ms);
if (ret <= 0) {
ostringstream ostr;
ms = linphone_core_get_upload_ptime(app->getCore());
ostr << "Ptime: " << ms << "\n";
app->sendResponse(Response(ostr.str().c_str(), Response::Ok));
} else if (ret == 1) {
ostringstream ostr;
linphone_core_set_upload_ptime(app->getCore(), ms);
ms = linphone_core_get_upload_ptime(app->getCore());
ostr << "Ptime: " << ms << "\n";
app->sendResponse(Response(ostr.str().c_str(), Response::Ok));
} else {
app->sendResponse(Response("Missing/Incorrect parameter(s)."));
}
}
};
class AudioCodecGetCommand: public DaemonCommand {
public:
AudioCodecGetCommand() :
DaemonCommand("audio-codec-get", "audio-codec-get <payload type number>", "Get an audio codec if codec-mime is defined, otherwise return the audio codec list.") {
}
virtual void exec(Daemon *app, const char *args) {
int payload_type;
bool list = sscanf(args, "%d", &payload_type) != 1;
bool find = list;
int index = 0;
ostringstream ostr;
for (const MSList *node = linphone_core_get_audio_codecs(app->getCore()); node != NULL; node = ms_list_next(node)) {
PayloadType *payload = reinterpret_cast<PayloadType*>(node->data);
if (list) {
ostr << PayloadTypeResponse(app->getCore(), payload, index).getBody() << "\n";
} else if (payload_type == linphone_core_get_payload_type_number(app->getCore(), payload)) {
ostr << PayloadTypeResponse(app->getCore(), payload, index).getBody();
find = true;
break;
}
++index;
}
if (!find) {
app->sendResponse(Response("Audio codec not found."));
} else {
app->sendResponse(Response(ostr.str().c_str(), Response::Ok));
}
}
};
class AudioCodecMoveCommand: public DaemonCommand {
public:
AudioCodecMoveCommand() :
DaemonCommand("audio-codec-move", "audio-codec-move <payload type number> <index>", "Move a codec to the an index.") {
}
virtual void exec(Daemon *app, const char *args) {
int payload_type;
int index;
if (sscanf(args, "%d %d", &payload_type, &index) == 2 && index >= 0) {
PayloadType *selected_payload = NULL;
for (const MSList *node = linphone_core_get_audio_codecs(app->getCore()); node != NULL; node = ms_list_next(node)) {
PayloadType *payload = reinterpret_cast<PayloadType*>(node->data);
if (payload_type == linphone_core_get_payload_type_number(app->getCore(), payload)) {
selected_payload = payload;
break;
}
}
if (selected_payload == NULL) {
app->sendResponse(Response("Audio codec not found."));
return;
}
int i = 0;
MSList *mslist = NULL;
for (const MSList *node = linphone_core_get_audio_codecs(app->getCore()); node != NULL; node = ms_list_next(node)) {
PayloadType *payload = reinterpret_cast<PayloadType*>(node->data);
if (i == index) {
mslist = ms_list_append(mslist, selected_payload);
++i;
}
if (selected_payload != payload) {
mslist = ms_list_append(mslist, payload);
++i;
}
}
if (i <= index) {
index = i;
mslist = ms_list_append(mslist, selected_payload);
}
linphone_core_set_audio_codecs(app->getCore(), mslist);
app->sendResponse(PayloadTypeResponse(app->getCore(), selected_payload, index));
} else {
app->sendResponse(Response("Missing/Incorrect parameter(s)."));
}
}
};
class AudioCodecEnableCommand: public DaemonCommand {
public:
AudioCodecEnableCommand() :
DaemonCommand("audio-codec-enable", "audio-codec-enable <payload type number>", "Enable an audio codec.") {
}
virtual void exec(Daemon *app, const char *args) {
int payload_type;
if (sscanf(args, "%d", &payload_type) == 1) {
int index = 0;
for (const MSList *node = linphone_core_get_audio_codecs(app->getCore()); node != NULL; node = ms_list_next(node)) {
PayloadType *payload = reinterpret_cast<PayloadType*>(node->data);
if (payload_type == linphone_core_get_payload_type_number(app->getCore(), payload)) {
linphone_core_enable_payload_type(app->getCore(), payload, true);
app->sendResponse(PayloadTypeResponse(app->getCore(), payload, index));
return;
}
++index;
}
app->sendResponse(Response("Audio codec not found."));
} else {
app->sendResponse(Response("Missing/Incorrect parameter(s)."));
}
}
};
class AudioCodecDisableCommand: public DaemonCommand {
public:
AudioCodecDisableCommand() :
DaemonCommand("audio-codec-disable", "audio-codec-disable <payload type number>", "Disable an audio codec.") {
}
virtual void exec(Daemon *app, const char *args) {
int payload_type;
if (sscanf(args, "%d", &payload_type) == 1) {
int index = 0;
for (const MSList *node = linphone_core_get_audio_codecs(app->getCore()); node != NULL; node = ms_list_next(node)) {
PayloadType *payload = reinterpret_cast<PayloadType*>(node->data);
if (payload_type == linphone_core_get_payload_type_number(app->getCore(), payload)) {
linphone_core_enable_payload_type(app->getCore(), payload, false);
app->sendResponse(PayloadTypeResponse(app->getCore(), payload, index));
return;
}
++index;
}
app->sendResponse(Response("Audio codec not found."));
} else {
app->sendResponse(Response("Missing/Incorrect parameter(s)."));
}
}
};
class AnswerCommand: public DaemonCommand {
public:
AnswerCommand() :
DaemonCommand("answer", "answer <call id>", "Answer an incoming call.") {
}
virtual void exec(Daemon *app, const char *args) {
LinphoneCore *lc = app->getCore();
int cid;
LinphoneCall *call;
if (sscanf(args, "%i", &cid) == 1) {
call = app->findCall(cid);
if (call == NULL) {
app->sendResponse(Response("No call with such id."));
return;
} else {
LinphoneCallState cstate = linphone_call_get_state(call);
if (cstate == LinphoneCallIncomingReceived || cstate == LinphoneCallIncomingEarlyMedia) {
if (linphone_core_accept_call(lc, call) == 0) {
app->sendResponse(Response());
return;
}
}
app->sendResponse(Response("Can't accept this call."));
return;
}
} else {
for (const MSList* elem = linphone_core_get_calls(lc); elem != NULL; elem = elem->next) {
call = (LinphoneCall*) elem->data;
LinphoneCallState cstate = linphone_call_get_state(call);
if (cstate == LinphoneCallIncomingReceived || cstate == LinphoneCallIncomingEarlyMedia) {
if (linphone_core_accept_call(lc, call) == 0) {
app->sendResponse(Response());
return;
}
}
}
}
app->sendResponse(Response("No call to accept."));
}
};
EventResponse::EventResponse(LinphoneCall *call, LinphoneCallState state) {
ostringstream ostr;
char *remote = linphone_call_get_remote_address_as_string(call);