From a54078ccf090907f1ebd9ddc3a02cd613ffecf9c Mon Sep 17 00:00:00 2001 From: Super User Date: Sun, 15 Jul 2007 12:03:09 +0200 Subject: [PATCH] backup --- asterisk_client.c | 197 +++++++++++++++++++++++++++++++++++++++ callchan.cpp => callasterisk.cpp | 84 +++++++++++------ callchan.h => callasterisk.h | 12 +-- save.h => macro.h | 47 +++++++++- 4 files changed, 301 insertions(+), 39 deletions(-) create mode 100644 asterisk_client.c rename callchan.cpp => callasterisk.cpp (51%) rename callchan.h => callasterisk.h (72%) rename save.h => macro.h (54%) diff --git a/asterisk_client.c b/asterisk_client.c new file mode 100644 index 0000000..386ea40 --- /dev/null +++ b/asterisk_client.c @@ -0,0 +1,197 @@ +/*****************************************************************************\ +** ** +** LCR ** +** ** +**---------------------------------------------------------------------------** +** Copyright: Andreas Eversberg ** +** ** +** Asterisk socket client ** +** ** +\*****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "macro.h" +#include "extension.h" +#include "message.h" +#include "admin.h" + +int sock; + +struct admin_list { + struct admin_list *next; + struct admin_msg msg; +} *admin_first = NULL; + +/* + * enque message from asterisk + */ +int admin_asterisk(int message_type, union parameter *param) +{ + struct admin_list *admin, **adminp; + + adminp = &admin_first; + while(*adminp) + adminp = &((*adminp)->next); + admin = (struct admin_list *)MALLOC(sizeof(struct admin_list)); + *adminp = admin; + + admin->msg.type = message_type; + memcpy(&admin->msg.param, param, sizeof(union parameter)); + + return(0); +} + + +/* asterisk handler + * warning! not thread safe + * returns -1 for socket error, 0 for no work, 1 for work + */ +int handle_socket(void) +{ + int work = 0; + int len; + struct admin_message msg; + struct admin_list *admin; + + /* read from socket */ + len = read(sock, &msg, sizeof(msg)); + if (len == 0) + { + printf("Socket closed\n"); + return(-1); // socket closed + } + if (len > 0) + { + if (len != sizeof(msg)) + { + fprintf(stderr, "Socket short read (%d)\n", len); + return(-1); // socket error + } + if (msg.message != ADMIN_MESSAGE) + { + fprintf(stderr, "Socket received illegal message %d\n", msg.message); + return(-1); // socket error + } + printf("message received %d\n", msg.u.msg.type); + work = 1; + } else + { + if (errno != EWOULDBLOCK) + { + fprintf(stderr, "Socket error %d\n", errno); + return(-1); + } + } + + /* write to socket */ + if (!admin_first) + return(work); + admin = admin_first; + len = write(sock, &admin->msg, sizeof(msg)); + if (len == 0) + { + printf("Socket closed\n"); + return(-1); // socket closed + } + if (len > 0) + { + if (len != sizeof(msg)) + { + fprintf(stderr, "Socket short write (%d)\n", len); + return(-1); // socket error + } + /* free head */ + admin_first = admin->next; + FREE(admin, 0); + + work = 1; + } else + { + if (errno != EWOULDBLOCK) + { + fprintf(stderr, "Socket error %d\n", errno); + return(-1); + } + } + + return(work); +} + +/* + * main function + */ +int main(int argc, char *argv[]) +{ + char *socket_name = SOCKET_NAME; + int conn; + struct sockaddr_un sock_address; + int ret; + unsigned long on = 1; + union parameter hello_param; + + /* open socket */ + if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) + { + fprintf(stderr, "Failed to create socket.\n"); + exit(EXIT_FAILURE); + } + + /* set socket address and name */ + memset(&sock_address, 0, sizeof(sock_address)); + sock_address.sun_family = PF_UNIX; + UCPY(sock_address.sun_path, socket_name); + + /* connect socket */ + if ((conn = connect(sock, (struct sockaddr *)&sock_address, SUN_LEN(&sock_address))) < 0) + { + close(sock); + fprintf(stderr, "Failed to connect to socket \"%s\".\nIs LCR running?\n", sock_address.sun_path); + exit(EXIT_FAILURE); + } + + /* set non-blocking io */ + if (ioctl(sock, FIONBIO, (unsigned char *)(&on)) < 0) + { + close(sock); + fprintf(stderr, "Failed to set socket into non-blocking IO.\n"); + exit(EXIT_FAILURE); + } + + /* enque hello message */ + memset(&hello_param, 0, sizeof(hello_param)); + admin_asterisk(MESSAGE_HELLO, &hello_param); + + while(42) + { + ret = handle_socket(); + if (ret < 0) + break; + if (!ret) + usleep(30000); + } + + /* close socket */ + close(sock); + /* now we say good bye */ + if (ret) + { + printf("%s\n", ret); + exit(EXIT_FAILURE); + } +} + + + + + diff --git a/callchan.cpp b/callasterisk.cpp similarity index 51% rename from callchan.cpp rename to callasterisk.cpp index a3c7599..0e7719f 100644 --- a/callchan.cpp +++ b/callasterisk.cpp @@ -28,60 +28,82 @@ * constructor for a new call * the call will have a relation to the calling endpoint */ -CallChan::CallChan(class Endpoint *epoint) : Call(epoint) +CallAsterisk::CallAsterisk(unsigned long serial) : Call() { - if (!epoint) - { - PERROR("software error, epoint is NULL.\n"); - exit(-1); - } - - PDEBUG(DEBUG_CALL, "creating new call and connecting it to the endpoint.\n"); + PDEBUG(DEBUG_CALL, "Constructor(new call)"); c_type = CALL_TYPE_ASTERISK; - c_epoint_id = epoint->ep_serial; - PDEBUG(DEBUG_CALL, "Constructor(new call)"); + c_epoint_id = serial; + if (c_epoint_id) + PDEBUG(DEBUG_CALL, "New call connected to endpoint id %lu\n", c_epoint_id); } /* * call descructor */ -CallChan::~CallChan() +CallAsterisk::~CallAsterisk() { } -/* release call from endpoint - * if the call has two relations, all relations are freed and the call will be - * destroyed - */ -void CallChan::release(unsigned long epoint_id, int hold, int location, int cause) -{ - if (!epoint_id) - { - PERROR("software error, epoint is NULL.\n"); - return; - } - - c_epoint_id = 0; - - PDEBUG(DEBUG_CALL, "call_release(): ended.\n"); -} - - /* call process is called from the main loop * it processes the current calling state. * returns 0 if call nothing was done */ -int CallChan::handler(void) +int CallAsterisk::handler(void) { return(0); } -void CallChan::message_epoint(unsigned long epoint_id, int message_type, union parameter *param) + +void CallAsterisk::message_epoint(unsigned long epoint_id, int message_type, union parameter *param) +{ + /* if endpoint has just been removed, but still a message in the que */ + if (epoint_id != c_epoint_id) + return; + + /* look for asterisk's interface */ + if (admin_message_from_join(epoint_id, message_type, param)<0) + { + PERROR("No socket with asterisk found, this shall not happen. Closing socket shall cause release of all asterisk calls\n"); + return; + } + + if (message_type == MESSAGE_RELEASE) + { + delete this; + return; + } +} + +void CallAsterisk::message_asterisk(unsigned long callref, int message_type, union parameter *param) { + struct message *message; + + /* create relation if no relation exists */ + if (!c_epoint_id) + { + class Endpoint *epoint; + + if (!(epoint = new Endpoint(0, c_serial, callref))) + FATAL("No memory for Endpoint instance\n"); + if (!(epoint->ep_app = new DEFAULT_ENDPOINT_APP(epoint))) + FATAL("No memory for Endpoint Application instance\n"); + } + + message = message_create(c_serial, c_epoint_id, CALL_TO_EPOINT, message_type); + memcpy(&message->param, param, sizeof(message->param)); + message_put(message); + + if (message_type == MESSAGE_RELEASE) + { + delete this; + return; + } } + + diff --git a/callchan.h b/callasterisk.h similarity index 72% rename from callchan.h rename to callasterisk.h index 080bdbe..f0573df 100644 --- a/callchan.h +++ b/callasterisk.h @@ -1,22 +1,22 @@ /*****************************************************************************\ ** ** -** PBX4Linux ** +** LCR ** ** ** **---------------------------------------------------------------------------** ** Copyright: Andreas Eversberg ** ** ** -** call header file for channel interface ** +** call header file for Asterisk interface ** ** ** \*****************************************************************************/ -class CallChan : public Call +class CallAsterisk : public Call { public: - CallChan(class Endpoint *epoint); - ~CallChan(); + CallAsterisk(unsigned long serial); + ~CallAsterisk(); void message_epoint(unsigned long epoint_id, int message, union parameter *param); + void message_asterisk(unsigned long callref, int message_type, union parameter *param); int handler(void); - void release(unsigned long epoint_id, int hold, int location, int cause); unsigned long c_epoint_id; }; diff --git a/save.h b/macro.h similarity index 54% rename from save.h rename to macro.h index 9b2d8a9..9bb1f29 100644 --- a/save.h +++ b/macro.h @@ -1,11 +1,12 @@ /*****************************************************************************\ ** ** -** PBX4Linux ** +** LCR ** ** ** **---------------------------------------------------------------------------** ** Copyright: Andreas Eversberg ** ** ** -** Macros to do save string operations to avoid buffer overflows. ** +** Macros to do safe string operations to avoid buffer overflows ** +** Macros for memory allocation, feeing and error handling ** ** ** \*****************************************************************************/ @@ -62,3 +63,45 @@ extern __inline__ void sprint(char *dst, unsigned int siz, char *fmt, ...) #define UNPRINT snprintf #define VUNPRINT vsnprintf +/* fatal error with error message and exit */ +#define FATAL(fmt, arg...) fatal(__FUNCTION__, __LINE__, fmt, ##arg) +extern __inline__ void fatal(const char *function, int line, char *fmt, ...) +{ + va_list args; + char buffer[256]; + + va_start(args, fmt); + vsnprintf(buffer, sizeof(buffer), fmt, args); + va_end(args); + buffer[sizeof(buffer)-1] = '\0'; + fprintf(stderr, "FATAL ERROR in function %s, line %d: %s", function, line, buffer); + fprintf(stderr, "This error is not recoverable, must exit here.\n"); +#ifdef DEBUG_FUNC + debug(function, line, "FATAL ERROR", buffer); + debug(function, line, "FATAL ERROR", "This error is not recoverable, must exit here.\n"); +#endif + exit(EXIT_FAILURE); +} + +/* memory allocation with setting to zero */ +#define MALLOC(size) _malloc(size, __FUNCTION__, __LINE__) +extern __inline__ void *_malloc(unsigned long size, const char *function, int line) +{ + void *addr; + addr = malloc(size); + if (!addr) + fatal(function, line, "No memory for %d bytes.\n", size); + memset(addr, 0, size); + return(addr); +} + +/* memory freeing with clearing memory to prevent using freed memory */ +#define FREE(addr, size) _free(addr, size) +extern __inline void _free(void *addr, int size) +{ + if (size) + memset(addr, 0, size); + free(addr); +} + + -- 2.13.6