Do proper bounds checking in formats (bug #1356)
[asterisk/asterisk.git] / formats / format_gsm.c
index 49d53df..d58039e 100755 (executable)
@@ -17,6 +17,7 @@
 #include <asterisk/logger.h>
 #include <asterisk/sched.h>
 #include <asterisk/module.h>
+#include <netinet/in.h>
 #include <arpa/inet.h>
 #include <stdlib.h>
 #include <sys/time.h>
 #endif
 #include "msgsm.h"
 
-
-/* Some Ideas for this code came from makegsme.c by Jeffery Chilton */
+/* Some Ideas for this code came from makegsme.c by Jeffrey Chilton */
 
 /* Portions of the conversion code are by guido@sienanet.it */
 
+/* silent gsm frame */
+/* begin binary data: */
+char gsm_silence[] = /* 33 */
+{0xD8,0x20,0xA2,0xE1,0x5A,0x50,0x00,0x49,0x24,0x92,0x49,0x24,0x50,0x00,0x49
+,0x24,0x92,0x49,0x24,0x50,0x00,0x49,0x24,0x92,0x49,0x24,0x50,0x00,0x49,0x24
+,0x92,0x49,0x24};
+/* end binary data. size = 33 bytes */
+
 struct ast_filestream {
        void *reserved[AST_RESERVED_POINTERS];
        /* Believe it or not, we must decode/recode to account for the
@@ -50,7 +58,7 @@ struct ast_filestream {
 };
 
 
-static pthread_mutex_t gsm_lock = AST_MUTEX_INITIALIZER;
+static ast_mutex_t gsm_lock = AST_MUTEX_INITIALIZER;
 static int glistcnt = 0;
 
 static char *name = "gsm";
@@ -65,7 +73,7 @@ static struct ast_filestream *gsm_open(int fd)
        struct ast_filestream *tmp;
        if ((tmp = malloc(sizeof(struct ast_filestream)))) {
                memset(tmp, 0, sizeof(struct ast_filestream));
-               if (ast_pthread_mutex_lock(&gsm_lock)) {
+               if (ast_mutex_lock(&gsm_lock)) {
                        ast_log(LOG_WARNING, "Unable to lock gsm list\n");
                        free(tmp);
                        return NULL;
@@ -78,7 +86,7 @@ static struct ast_filestream *gsm_open(int fd)
                tmp->fr.src = name;
                tmp->fr.mallocd = 0;
                glistcnt++;
-               ast_pthread_mutex_unlock(&gsm_lock);
+               ast_mutex_unlock(&gsm_lock);
                ast_update_use_count();
        }
        return tmp;
@@ -92,14 +100,14 @@ static struct ast_filestream *gsm_rewrite(int fd, char *comment)
        struct ast_filestream *tmp;
        if ((tmp = malloc(sizeof(struct ast_filestream)))) {
                memset(tmp, 0, sizeof(struct ast_filestream));
-               if (ast_pthread_mutex_lock(&gsm_lock)) {
+               if (ast_mutex_lock(&gsm_lock)) {
                        ast_log(LOG_WARNING, "Unable to lock gsm list\n");
                        free(tmp);
                        return NULL;
                }
                tmp->fd = fd;
                glistcnt++;
-               ast_pthread_mutex_unlock(&gsm_lock);
+               ast_mutex_unlock(&gsm_lock);
                ast_update_use_count();
        } else
                ast_log(LOG_WARNING, "Out of memory\n");
@@ -108,12 +116,12 @@ static struct ast_filestream *gsm_rewrite(int fd, char *comment)
 
 static void gsm_close(struct ast_filestream *s)
 {
-       if (ast_pthread_mutex_lock(&gsm_lock)) {
+       if (ast_mutex_lock(&gsm_lock)) {
                ast_log(LOG_WARNING, "Unable to lock gsm list\n");
                return;
        }
        glistcnt--;
-       ast_pthread_mutex_unlock(&gsm_lock);
+       ast_mutex_unlock(&gsm_lock);
        ast_update_use_count();
        close(s->fd);
        free(s);
@@ -185,12 +193,21 @@ static int gsm_seek(struct ast_filestream *fs, long sample_offset, int whence)
        distance = (sample_offset/160) * 33;
        if(whence == SEEK_SET)
                offset = distance;
-       if(whence == SEEK_CUR)
+       else if(whence == SEEK_CUR || whence == SEEK_FORCECUR)
                offset = distance + cur;
-       if(whence == SEEK_END)
+       else if(whence == SEEK_END)
                offset = max - distance;
-       offset = (offset > max)?max:offset;
+       // Always protect against seeking past the begining.
        offset = (offset < min)?min:offset;
+       if (whence != SEEK_FORCECUR) {
+               offset = (offset > max)?max:offset;
+       } else if (offset > max) {
+               int i;
+               lseek(fs->fd, 0, SEEK_END);
+               for (i=0; i< (offset - max) / 33; i++) {
+                       write(fs->fd, gsm_silence, 33);
+               }
+       }
        return lseek(fs->fd, offset, SEEK_SET);
 }
 
@@ -235,12 +252,12 @@ int unload_module()
 int usecount()
 {
        int res;
-       if (ast_pthread_mutex_lock(&gsm_lock)) {
+       if (ast_mutex_lock(&gsm_lock)) {
                ast_log(LOG_WARNING, "Unable to lock gsm list\n");
                return -1;
        }
        res = glistcnt;
-       ast_pthread_mutex_unlock(&gsm_lock);
+       ast_mutex_unlock(&gsm_lock);
        return res;
 }