backup
authorSuper User <root@isdn.jolly.ten>
Sun, 15 Jul 2007 10:03:09 +0000 (12:03 +0200)
committerSuper User <root@isdn.jolly.ten>
Sun, 15 Jul 2007 10:03:09 +0000 (12:03 +0200)
asterisk_client.c [new file with mode: 0644]
callasterisk.cpp [moved from callchan.cpp with 51% similarity]
callasterisk.h [moved from callchan.h with 72% similarity]
macro.h [moved from save.h with 54% similarity]

diff --git a/asterisk_client.c b/asterisk_client.c
new file mode 100644 (file)
index 0000000..386ea40
--- /dev/null
@@ -0,0 +1,197 @@
+/*****************************************************************************\
+**                                                                           **
+** LCR                                                                       **
+**                                                                           **
+**---------------------------------------------------------------------------**
+** Copyright: Andreas Eversberg                                              **
+**                                                                           **
+** Asterisk socket client                                                    **
+**                                                                           **
+\*****************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <time.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#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);
+       }
+}
+
+
+
+
+
similarity index 51%
rename from callchan.cpp
rename to callasterisk.cpp
index a3c7599..0e7719f 100644 (file)
  * 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;
+       }
 }
 
+
+
similarity index 72%
rename from callchan.h
rename to callasterisk.h
index 080bdbe..f0573df 100644 (file)
@@ -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 (file)
--- 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);
+}
+
+