Commit 89032270 authored by Gabriel Margiani's avatar Gabriel Margiani

first commit

parents
/**
* This file is part of 3phone
* Copyright (C) 2015 Gabriel Margiani
*
* 3phone is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 3phone 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 3phone. If not, see <http://www.gnu.org/licenses/>.
**/
#ifndef __3P_3PHONE_H__
#define __3P_3PHONE_H__
#include "error.h"
// pjloglevel
#ifndef DEBUG
#define LOGLEVEL 0
#else
#define LOGLEVEL 5
#endif
#define MAX_CALLS 20
// C !!
bool exit;
#endif
/**
* This file is part of 3phone
* Copyright (C) 2015 Gabriel Margiani
*
* 3phone is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 3phone 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 3phone. If not, see <http://www.gnu.org/licenses/>.
**/
#ifndef __P3_ACCOUNT_H__
#define __P3_ACCOUNT_H__
#include <pjsua2.hpp>
class p3Account : public pj::Account {
public:
p3Account() {};
~p3Account() {};
virtual void onRegState(OnRegStateParam &prm);
virtual void onIncomingCall(OnIncomingCallParam &iprm);
}
#endif
/**
* This file is part of 3phone
* Copyright (C) 2015 Gabriel Margiani
*
* 3phone is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 3phone 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 3phone. If not, see <http://www.gnu.org/licenses/>.
**/
#include <iostream>
#include <random>
#include <ctime>
#include <boost/algorithm/string.hpp>
#include "client.h"
#include "error.h"
std::map<std::string, std::string> p3::client::command_shorthands {
{"c", "call"}
};
p3::client::client(int ac, char *av[]) : argv(av, av+ac) {
argv.pop_front();
std::random_device rd;
std::default_random_engine e(rd());
std::uniform_int_distribution<int> uniform_dist(200, 900);
id = std::to_string(uniform_dist(e)) + std::to_string(std::time(NULL));
connection = nullptr;
try {
p3::mQueue ma(p3::mQueue::DefaultId, false);
connection = new mQueue(id, true);
ma.send(p3::protocol::HELLO, id);
p3::mQueueMessage m = ma.receive(30);
if (m.get_command() != p3::protocol::OK) {
throw new p3::perror("client.connection", "cannot connect to server " + m.get_value());
}
} catch (p3::perror & e) {
if (connection != nullptr) {
delete connection;
}
throw;
}
}
p3::client::~client() {
connection->send(p3::protocol::BYE, "Client Terminating");
delete connection;
}
std::string p3::client::get_input(std::string q, p3::client::inputType type) {
std::string in;
if (!argv.empty()) {
in = argv.front();
argv.pop_front();
} else {
do {
std::cout << q << " > " << std::flush;
std::cin >> in;
boost::trim(in);
} while (in == "");
}
boost::to_lower(in);
if (type == COMMAND && p3::client::command_shorthands.count(in) == 1) {
return p3::client::command_shorthands[in];
}
return in;
}
void p3::client::run() {
bool r = true;
connection->send(p3::protocol::COMMAND, get_input("", COMMAND));
while (r) {
p3::mQueueMessage m = connection->receive(-1);
switch (m.get_command()) {
case p3::protocol::ASK_NUMBER:
connection->send(p3::protocol::ANSWER, get_input(m.get_value(), NUMBER));
continue;
case p3::protocol::OK:
std::cout << m.get_value() << std::endl;
break;
case p3::protocol::ERROR:
std::cout << "ERROR: " << m.get_value() << std::endl;
break;
case p3::protocol::FATAL_ERROR:
std::cout << "FATAL ERROR: " << m.get_value() << std::endl;
case p3::protocol::BYE:
std::cout << "done." << std::endl;
r = false;
continue;
default:
std::cout << "Unknown server command. " << m.get_value() << std::endl;
}
std::string in = get_input("", COMMAND);
if (in == "exit" || in == "quit") {
break;
} else {
connection->send(p3::protocol::COMMAND, in);
}
}
}
/**
* This file is part of 3phone
* Copyright (C) 2015 Gabriel Margiani
*
* 3phone is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 3phone 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 3phone. If not, see <http://www.gnu.org/licenses/>.
**/
#ifndef __P3_CLIENT_H__
#define __P3_CLIENT_H__
#include <string>
#include <list>
#include <map>
#include "msgq.h"
namespace p3 {
class client {
mQueue * connection;
std::string id;
std::list<std::string> argv;
static std::map<std::string, std::string> command_shorthands;
enum inputType {
COMMAND,
NUMBER
};
std::string get_input(std::string question, inputType is_command);
public:
client(int argc, char *argv[]);
~client();
void run();
};
}
#endif
/**
* This file is part of 3phone
* Copyright (C) 2015 Gabriel Margiani
*
* 3phone is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 3phone 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 3phone. If not, see <http://www.gnu.org/licenses/>.
**/
#ifndef __P3_ERROR_H__
#define __P3_ERROR_H__
#include <string>
namespace p3 {
class perror : std::exception {
std::string context;
std::string error;
public:
perror(std::string c, std::string e) : context(c), error(e) {};
~perror() throw () {};
const char * getContext() { return context.c_str(); }
const char * getError() { return error.c_str(); }
const char* what() const throw() {
return (context + ": " + error).c_str();
}
};
}
#endif
/**
* This file is part of 3phone
* Copyright (C) 2015 Gabriel Margiani
*
* 3phone is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 3phone 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 3phone. If not, see <http://www.gnu.org/licenses/>.
**/
#include <iostream>
#include "server.h"
#include "client.h"
#include "msgq.h"
#include "error.h"
void print_usage() {
std::cout << "3phone - p3 usage: " << std::endl
<< "p3 s erve - start the server" << std::endl
<< "p3 c all [nr] - call someone" << std::endl
<< "p3 a nswer - answer a currently ringing call" << std::endl
<< "p3 l ist - list current calls" << std::endl
<< "p3 h angup [id] - hanup" << std::endl
<< "p3 p ause, hold [id] - pause/hold/reinvite" << std::endl
<< "p3 j oin - conference current calls" << std::endl
<< "p3 f orward [id] [nr] - forward call" << std::endl
<< "p3 r ecord [file] - record" << std::endl;
}
int run_server() {
try {
p3::server srv;
srv.run();
} catch (p3::mQueueException * e) {
std::cout << "Server Error: " << e->what() << std::endl;
return 1;
}
return 0;
}
int run_client(int argc, char *argv[]) {
try {
p3::client cl(argc, argv);
cl.run();
} catch (p3::perror const & e) {
std::cout << "Client Error: " << e.what() << std::endl;
return 1;
}
return 0;
}
int send_quit() {
try {
p3::mQueue q(p3::mQueue::DefaultId);
q.send(p3::protocol::QUIT, "Terminate server");
} catch (p3::perror const & e) {
std::cout << "Termination Error: " << e.what() << std::endl;
return 1;
}
return 0;
}
int main(int argc, char *argv[]) {
if (argc > 1) {
std::string a = argv[1];
if (a == "-h" || a == "--help" || a == "help") {
print_usage();
} else if (a == "s" || a == "serve" || a == "server") {
return run_server();
} else if (a == "quit" || a == "stop") {
return send_quit();
} else {
return run_client(argc, argv);
}
} else {
print_usage();
return 1;
}
return 0;
}
/**
* This file is part of 3phone
* Copyright (C) 2015 Gabriel Margiani
*
* 3phone is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 3phone 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 3phone. If not, see <http://www.gnu.org/licenses/>.
**/
#include <cerrno>
#include <ctime>
#include "msgq.h"
const bool p3::mQueue::Create = true;
const int p3::mQueue::DefaultSendTimeout = 10; /* 10sec timeout... */
const char * p3::mQueue::DefaultId = "p3Main";
p3::mQueue::mQueue(std::string id, bool c) {
delOnDestruct = c;
key = "/p3::mQueue!" + id;
int flags = 0;
if (c) {
flags |= O_CREAT;
inkey = key + "-2";
outkey = key + "-1";
} else {
inkey = key + "-1";
outkey = key + "-2";
}
mq_attr attr;
attr.mq_flags = 0;
attr.mq_maxmsg = 30;
attr.mq_msgsize = 253;
attr.mq_curmsgs = 0;
mqInId = mq_open(inkey.c_str(), flags | O_RDONLY, 01777, &attr);
mqOutId = mq_open(outkey.c_str(), flags | O_WRONLY, 01777, &attr);
if (mqInId == -1 || mqOutId == -1) {
int err = errno;
if (mqInId != -1) {
mq_close(mqInId);
if (c) mq_unlink(inkey.c_str());
} else if (mqOutId != -1) {
mq_close(mqOutId);
if (c) mq_unlink(outkey.c_str());
}
switch (err) {
case EACCES:
throw p3::mQueueException(key + ":open", "Access Denied");
case EMFILE:
case ENOSPC:
throw p3::mQueueException(key + ":open", "to many open queues");
case ENOENT:
throw p3::mQueueException(key + ":open", "does not exist");
case ENOMEM:
throw p3::mQueueException(key + ":open", "Memory full");
default:
throw p3::mQueueException(key + ":open", "Open or Creation failed: " + errno);
}
}
}
p3::mQueue::~mQueue() {
if (mqInId != -1) {
mq_close(mqInId);
if (delOnDestruct) {
mq_unlink(inkey.c_str());
}
}
if (mqOutId != -1) {
mq_close(mqOutId);
if (delOnDestruct) {
mq_unlink(outkey.c_str());
}
}
}
void p3::mQueue::send(p3::protocol c, std::string v) {
p3::mQueueMessage q = p3::mQueueMessage(c, v);
send(q);
}
void p3::mQueue::send(p3::mQueueMessage & qmsg) {
std::string msg = qmsg.get_str();
timespec tsp;
tsp.tv_sec = time(NULL) + DefaultSendTimeout;
tsp.tv_nsec = 0;
if (mq_timedsend(mqOutId, msg.c_str(), msg.length()+1, 0, &tsp) != 0) {
switch (errno) {
case EINVAL:
throw p3::mQueueException(key + ":send", "Timeout invalid");
case EMSGSIZE:
throw p3::mQueueException(key + ":send", "Message to big: " + msg);
case ETIMEDOUT:
throw p3::mQueueException(key + ":send", "Queue full, Timeout");
default:
throw p3::mQueueException(key + ":send", "Failed to send Message: " + msg);
}
}
}
p3::mQueueMessage p3::mQueue::receive(int timeout) {
ssize_t ret;
char buf[254];
if (timeout != -1) {
timespec tsp;
tsp.tv_sec = time(NULL) + timeout;
tsp.tv_nsec = 0;
ret = mq_timedreceive(mqInId, buf, 253, NULL, &tsp);
} else {
ret = mq_receive(mqInId, buf, 253, NULL);
}
if (ret != -1) {
buf[ret] = '\0';
return p3::mQueueMessage(buf);
} else {
switch (errno) {
case EINVAL:
throw p3::mQueueException(key + ":recv", "Timeout invalid");
case ETIMEDOUT:
throw p3::mQueueException(key + ":recv", "Queue full, Timeout");
default:
throw p3::mQueueException(key + ":recv", "Failed to receive");
}
}
}
long p3::mQueue::get_msg_count() {
mq_attr attr;
mq_getattr(mqInId, &attr);
return attr.mq_curmsgs;
}
p3::mQueueMessage::mQueueMessage(const char * message) : command(static_cast<p3::protocol>(*message)), value(message+1) {};
p3::mQueueMessage::mQueueMessage(protocol c, std::string &v) : command(c), value(v) {};
p3::protocol p3::mQueueMessage::get_command() {
return command;
}
std::string& p3::mQueueMessage::get_value() {
return value;
}
std::string p3::mQueueMessage::get_str() {
return static_cast<char>(command) + value;
}
/**
* This file is part of 3phone
* Copyright (C) 2015 Gabriel Margiani
*
* 3phone is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 3phone 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 3phone. If not, see <http://www.gnu.org/licenses/>.
**/
#ifndef __P3_MSGQ_H__
#define __P3_MSGQ_H__
#include <string>
#include <mqueue.h>
#include "error.h"
#include "protocol.h"
namespace p3 {
class mQueueMessage {
protocol command;
std::string value;
public:
explicit mQueueMessage(const char * message);
mQueueMessage(protocol c, std::string &v);
protocol get_command();
std::string& get_value();
std::string get_str();
};
/* Message queue */
class mQueue {
mqd_t mqInId;
mqd_t mqOutId;
std::string key;
std::string inkey;
std::string outkey;
bool delOnDestruct;
public:
static const bool Create;
static const int DefaultSendTimeout;
static const char * DefaultId;
// create implies delete on destruct.
mQueue(std::string id, bool create = false);
~mQueue();
void send(mQueueMessage & m);
void send(protocol c, std::string w);
// Timeout in sec. -1 for blocking. Will throw on timeout!
mQueueMessage receive(int timeout = -1);
// How many Messages are currently on queue
long get_msg_count();
};
class mQueueException : public perror {
public:
mQueueException(std::string c, std::string e) : perror("p3mq:" + c, e) {}
};
}
#endif
/**
* This file is part of 3phone
* Copyright (C) 2015 Gabriel Margiani
*
* 3phone is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 3phone 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 3phone. If not, see <http://www.gnu.org/licenses/>.
**/
#include <iostream>
#include "phonebook.h"
std::string p3::phonebook::parse_number(std::string nr) {
std::cout << "parsing Number " << nr << std::endl;
return nr;
}
/**
* This file is part of 3phone
* Copyright (C) 2015 Gabriel Margiani
*
* 3phone is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 3phone 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 3phone. If not, see <http://www.gnu.org/licenses/>.
**/
#ifndef __P3_PHONEBOOK_H__
#define __P3_PHONEBOOK_H__
#include <string>
namespace p3 {
class phonebook {
public:
std::string parse_number(std::string nr);
};
}
#endif
/**
* This file is part of 3phone
* Copyright (C) 2015 Gabriel Margiani
*
* 3phone is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 3phone 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 3phone. If not, see <http://www.gnu.org/licenses/>.
**/
#ifndef __P3_PROTOCOL_H__
#define __P3_PROTOCOL_H__
namespace p3 {
enum class protocol : char {
HELLO,
BYE,
QUIT,
SET_TIMEOUT,
COMMAND,
OK,
ASK,
ASK_NUMBER,
ANSWER,
BEGINTEXT,
TEXT,
ENDTEXT,
ERROR,
FATAL_ERROR
};
}
#endif
/**
* This file is part of 3phone
* Copyright (C) 2015 Gabriel Margiani
*
* 3phone is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 3phone 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 3phone. If not, see <http://www.gnu.org/licenses/>.
**/