From f9a34a1aeac102a3f52ecfa1e2d39e0be054eaa1 Mon Sep 17 00:00:00 2001 From: bagyenda <> Date: Sat, 19 Mar 2005 06:46:24 +0000 Subject: [PATCH] Added mmbox handler module, fixes to message coder/decoder. --- mbuni/mmlib/Makefile.am | 2 +- mbuni/mmlib/mms_mmbox.c | 735 ++++++++++++++++++++++++++++++++++++++++ mbuni/mmlib/mms_mmbox.h | 14 + mbuni/mmlib/mms_msg.c | 45 ++- mbuni/mmlib/mms_msg.h | 6 + mbuni/mmlib/mms_queue.c | 57 +--- mbuni/mmlib/mms_queue.h | 5 +- mbuni/mmlib/mms_util.c | 64 +++- mbuni/mmlib/mms_util.h | 21 +- mbuni/mmsc/mmssend.c | 51 ++- 10 files changed, 930 insertions(+), 70 deletions(-) create mode 100644 mbuni/mmlib/mms_mmbox.c create mode 100644 mbuni/mmlib/mms_mmbox.h diff --git a/mbuni/mmlib/Makefile.am b/mbuni/mmlib/Makefile.am index 934f9da..8bea4d8 100644 --- a/mbuni/mmlib/Makefile.am +++ b/mbuni/mmlib/Makefile.am @@ -1,5 +1,5 @@ noinst_LIBRARIES = libmms.a -libmms_a_SOURCES = mms_billing.c mms_billing.h mms_msg.c mms_msg.h mms_queue.c mms_queue.h mms_strings.c mms_strings.h mms_uaprof.c mms_uaprof.h mms_util.c mms_util.h mms_resolve.c +libmms_a_SOURCES = mms_mmbox.h mms_mmbox.c mms_billing.c mms_billing.h mms_msg.c mms_msg.h mms_queue.c mms_queue.h mms_strings.c mms_strings.h mms_uaprof.c mms_uaprof.h mms_util.c mms_util.h mms_resolve.c plugindir = $(libdir)/mbuni plugin_LTLIBRARIES = libmms_billing_shell.la libmms_resolve_shell.la libmms_detokenize_shell.la diff --git a/mbuni/mmlib/mms_mmbox.c b/mbuni/mmlib/mms_mmbox.c new file mode 100644 index 0000000..a5a9214 --- /dev/null +++ b/mbuni/mmlib/mms_mmbox.c @@ -0,0 +1,735 @@ +/* + * MMS MMBox management module - P. A. Bagyenda + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mms_mmbox.h" +#include "mms_util.h" +#include "gwlib/log.h" +#include "gwlib/accesslog.h" + +#define MAXTRIES 10 +#define MDF 'd' +#define MTF 't' +#define IDXFILE "00Index" + +#define ITEM_ADD 1 +#define ITEM_DEL 2 +#define ITEM_MOD 3 + +#define _TT "0123456789abcdefghijklmnopqrstuvwxyz" +#define _TTSIZE (-1 + sizeof _TT) + +static unsigned long hash(char *s) +{ + unsigned h = 0; + + while (*s) { + unsigned int ch = tolower(*s); + s++; + h += ((unsigned)(ch) << 4) + 1249; + } + return h; +} + + +/* Initialise the root of the mmbox. Should be called once from load settings. */ +int mmbox_root_init(char *mmbox_root) +{ + int i, ret; + if ((ret = mkdir(mmbox_root, + S_IRWXU|S_IRWXG)) < 0 && + errno != EEXIST) + return errno; + for (i = 0; _TT[i]; i++) { + char fbuf[256]; + + sprintf(fbuf, "%.128s/%c", mmbox_root, _TT[i]); + if (mkdir(fbuf, + S_IRWXU|S_IRWXG) < 0 && + errno != EEXIST) + return errno; + } + srandom(time(NULL)); /* we need rands below...*/ + + return 0; +} + +/* Initialise the mmbox home of the user/msisdn. + * structure of mmbox is: + * - index file [IDXFILE] + * - directories a - z 0 - 9, which each can contain directories with two-character + * names + * on init we only create the directory itself. internal + * directory structure and index will be made by first message put in. + * return user dir, or NULL if something went wrong. + */ +static Octstr *user_mmbox_dir(char *mmbox_root, char *userid) +{ + + unsigned long h = hash(userid); + char d1[2], d2[3], fbuf[512]; + Octstr *t, *s; + + /* Make toplevel dir. */ + d1[0] = _TT[h%_TTSIZE]; + d1[1] = '\0'; + + /* Then lower level. */ + h /= _TTSIZE; + d2[0] = _TT[h%_TTSIZE]; + h /= _TTSIZE; + d2[1] = _TT[h%_TTSIZE]; + d2[2] = '\0'; + + /* Try and create the next level dir (first level was created by root_init) */ + sprintf(fbuf, "%.128s/%s/%s", mmbox_root, d1, d2); + if (mkdir(fbuf, + S_IRWXU|S_IRWXG) < 0 && + errno != EEXIST) { + error(0, "mmbox: failed to create dir [%s] " + "while initialising mmbox for %s: %s!", + fbuf, userid, strerror(errno)); + return NULL; + } + + t = octstr_create(userid); + octstr_replace(t, octstr_imm("/"), octstr_imm("$")); /* XXX safe in all cases?? */ + s = octstr_format("%s/%S", fbuf, t); + octstr_destroy(t); + + if (mkdir(octstr_get_cstr(s), + S_IRWXU|S_IRWXG) < 0 && + errno != EEXIST) { + error(0, "mmbox: failed to create dir [%s] " + "while initialising mmbox for %s: %s!", + octstr_get_cstr(s), userid, strerror(errno)); + octstr_destroy(s); + return NULL; + } + return s; +} + +/* Makes a file name in the nested directory structure, where we can store + * data. Makes a number of tries -- similar to mkqf in queue module. + */ +static int mkdf(char df[64], char *mmbox_home) +{ + + int i = 0, fd = -1; + static int ect; + + if (!mmbox_home) + gw_panic(0, "Mmbox directory passed as null!"); + + do { + char d1[2], d2[3]; + Octstr *tmp; + char *ctmp; + + d1[0] = _TT[random() % _TTSIZE]; + d1[1] = '\0'; + + /* Make first level. */ + tmp = octstr_format("%.128s/%s", mmbox_home, d1); + if (mkdir(octstr_get_cstr(tmp), + S_IRWXU|S_IRWXG) < 0 && + errno != EEXIST) { + error(0, "mmbox.mkdf: failed to create dir [%s] " + " in mmbox home %s: %s!", + octstr_get_cstr(tmp), mmbox_home, strerror(errno)); + octstr_destroy(tmp); + return -1; + } + + octstr_destroy(tmp); + + d2[0] = _TT[random() % _TTSIZE]; + d2[1] = _TT[random() % _TTSIZE]; + d2[2] = '\0'; + + /* Make second level. */ + tmp = octstr_format("%.128s/%s/%s", mmbox_home, d1,d2); + + if (mkdir(octstr_get_cstr(tmp), + S_IRWXU|S_IRWXG) < 0 && + errno != EEXIST) { + error(0, "mmbox.mkdf: failed to create dir [%s] " + " in mmbox home %s: %s!", + octstr_get_cstr(tmp), mmbox_home, strerror(errno)); + octstr_destroy(tmp); + return -1; + } + octstr_destroy(tmp); + + /* use df[] to store candidate so when we hit success it is already there...*/ + sprintf(df, "%s/%s/%cf%ld.%d.x%d%ld", + d1,d2, MDF, + time(NULL), + ++ect, getpid(), random() % 100); + tmp = octstr_format("%s/%s", mmbox_home, df); + ctmp = octstr_get_cstr(tmp); + fd = open(ctmp, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP); + if (fd >= 0 && + mm_lockfile(fd,ctmp,1) != 0) { + unlink(ctmp); + close(fd); + fd = -1; + } + octstr_destroy(tmp); + + } while (i++ < MAXTRIES && fd < 0); + + return fd; +} + +static int open_mmbox_index(char *mmbox_dir, int shouldblock) +{ + char fbuf[256]; + int i, fd; + + sprintf(fbuf, "%s/%s", mmbox_dir, IDXFILE); + + i = 0; + do + if ((fd = open(fbuf, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP)) < 0) { + error(0, "Failed to open mmbox index file [%s], error: %s!", + fbuf, strerror(errno)); + break; + } else if (mm_lockfile(fd, fbuf, shouldblock) != 0) { + close(fd); + fd = -1; + } + while (i++ < MAXTRIES && fd < 0); + + return fd; +} + +static Octstr *linearise_string_list(List *l, char *sep) +{ + int i, n; + + Octstr *s = octstr_create(""); + + for (i = 0, n = list_len(l); i < n; i++) { + Octstr *p = list_get(l,i); + if (p) + octstr_format_append(s, "%s%S", (i == 0) ? "" : sep, p); + } + return s; +} + +static List *parse_string_list(char *buf) +{ + int i = 0; + char sbuf[128], *p = buf; + List *l = list_create(); + + while (sscanf(p, "%s%n", sbuf, &i) > 0) { + list_append(l, octstr_create(sbuf)); + p += i; + } + + return l; +} + +static char *skip_space(char *s) +{ + while (*s && isspace(*s)) + s++; + return s; +} + +/* Format of Index file: + * each message is described by a single line: + * df state flag1 flag2 flag3 ... + */ +static int update_mmbox_index(int fd, char *mmbox_dir, int cmd, + Octstr *df, Octstr *state, List *flags) +{ + char fbuf[256], linbuf[1024]; + int tempfd; + FILE *fp; + + /* Make a temp file. */ + + sprintf(fbuf, "%.128s/t%s.%ld.%ld", + mmbox_dir, IDXFILE, time(NULL), random() % 1000); + + tempfd = open(fbuf, + O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP); + if (tempfd < 0 ) { + error(0, "mmbox.update_index: Failed to open temp file %s: error = %s\n", + fbuf, strerror(errno)); + + goto done; + } else if (mm_lockfile(tempfd, fbuf, 0) != 0) { /* Lock it. */ + error(0, "mmbox.update_index: Failed lock temp file %s: error = %s\n", + fbuf, strerror(errno)); + + close(tempfd); + tempfd = -1; + goto done; + + } + fp = fdopen(fd, "r"); + + if (!fp) { + error(0, "mmbox.update_index: Failed fdopen on tempfd, file %s: error = %s\n", + + fbuf, strerror(errno)); + + close(tempfd); + tempfd = -1; + goto done; + } + + while (fgets(linbuf, sizeof linbuf, fp) != NULL) { + char idx[128], xstate[32]; + Octstr *outs = NULL; + int i; + + sscanf(linbuf, "%s %s%n", idx, xstate, &i); + + if (df && octstr_str_compare(df, idx) == 0) + if (cmd == ITEM_DEL || cmd == ITEM_ADD) + goto loop; /* Skip it. */ + else { /* MOD. */ + Octstr *p = linearise_string_list(flags, " "); + outs = octstr_format("%S %S %S\n", df, state, p); + octstr_destroy(p); + } + else { /* Copy out as-is */ + outs = octstr_format("%s %s %s%s", + idx, xstate, + skip_space(linbuf + i), + (strchr(linbuf+i, '\n') >= 0 ? "" : "\n")); + } + loop: + if (outs) { + if (octstr_len(outs) > 0) + octstr_write_to_socket(tempfd, outs); + octstr_destroy(outs); + } + } + + if (cmd == ITEM_ADD) { /* Finally, for ADD, just add it. */ + Octstr *s, *p = linearise_string_list(flags, " "); + s = octstr_format("%S %S %S\n", df, state, p); + octstr_destroy(p); + octstr_write_to_socket(tempfd, s); + octstr_destroy(s); + } + fsync(tempfd); + + sprintf(linbuf, "%.128s/%s", + mmbox_dir, IDXFILE); + rename(fbuf, linbuf); + + fclose(fp); + done: + + return tempfd; +} + +static List *make_mm_flags(List *oflags, List *flag_cmds) +{ + List *l = oflags ? oflags : list_create(); + int i, n; + + for (i = 0, n = list_len(l); i < n; i++) { /* cleanup list. */ + Octstr *x = list_get(l,i); + int ch = octstr_get_char(x, 0); + + if (ch == '+' || ch == '-' || ch == '/') + octstr_delete(x,0,1); + } + + for (i = 0, n = (flag_cmds ? list_len(flag_cmds) : 0); i 0) + close(dfd); + if (ifd > 0) + close(ifd); + + if (s) + octstr_destroy(s); + if (home) + octstr_destroy(home); + if (state) + octstr_destroy(state); + if (flags) + list_destroy(flags, (list_item_destructor_t *)octstr_destroy); + if (flag_cmds) + list_destroy(flag_cmds, (list_item_destructor_t *)octstr_destroy); + + return sdf; +} + +int mms_mmbox_modmsg(char *mmbox_root, char *user, Octstr *msgref, + Octstr *state, List *flag_cmds) +{ + Octstr *sdf = octstr_duplicate(msgref); + Octstr *fname = NULL, *ftmp = NULL; + Octstr *home = user_mmbox_dir(mmbox_root,user); + Octstr *s = NULL; + List *flags = NULL; + Octstr *nstate = NULL; + + int ifd = -1, nifd, tmpfd = -1; + MmsMsg *m = NULL; + int res = -1; + + octstr_replace(sdf, octstr_imm("-"), octstr_imm("/")); + + if (!home) + goto done; + + ifd = open_mmbox_index(octstr_get_cstr(home),1); + + if (ifd < 0) + goto done; + + fname = octstr_format("%S/%S", home, sdf); + s = octstr_read_file(octstr_get_cstr(fname)); + + if ( s == NULL || octstr_len(s) == 0) { + error(0, "mmbox.mod: failed to read data file [%s] - %s!", + octstr_get_cstr(fname), strerror(errno)); + goto done; + } + + m = mms_frombinary(s, octstr_imm("anon@anon")); + + if (!m) { + error(0, "mmbox.mod: failed to read data file [%s]!", + octstr_get_cstr(fname)); + goto done; + } + + if (state == NULL) + nstate = mms_get_header_value(m, octstr_imm("X-Mms-MM-State")); + else { + nstate = octstr_duplicate(state); + mms_replace_header_value(m, "X-Mms-MM-State", octstr_get_cstr(nstate)); + } + + flags = mms_get_header_values(m, octstr_imm("X-Mms-MM-Flags")); + flags = make_mm_flags(flags, flag_cmds); + mms_replace_header_values(m, "X-Mms-MM-Flags", flags); + + + ftmp = octstr_format("%S.%ld.%d", fname, time(NULL), getpid()); + tmpfd = open(octstr_get_cstr(ftmp), O_RDWR|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP); + + if (tmpfd < 0) + goto done; + + s = mms_tobinary(m); + + octstr_write_to_socket(tmpfd, s); + + rename(octstr_get_cstr(ftmp), octstr_get_cstr(fname)); + close(tmpfd); + + if ((nifd = update_mmbox_index(ifd, octstr_get_cstr(home), ITEM_MOD, sdf, nstate, flags)) < 0) { + /* Not good, we wrote but could not update the index file. scream. */ + error(0, "mmbox.mod: failed to update index file, home is %s!", + octstr_get_cstr(home)); + goto done; + } + ifd = nifd; + res = 0; + + done: + if (ifd > 0) + close(ifd); + + if (fname) + octstr_destroy(fname); + + if (ftmp) + octstr_destroy(ftmp); + + if (sdf) + octstr_destroy(sdf); + + if (s) + octstr_destroy(s); + if (home) + octstr_destroy(home); + if (nstate) + octstr_destroy(nstate); + if (flags) + list_destroy(flags, (list_item_destructor_t *)octstr_destroy); + if (m) + mms_destroy(m); + return res; +} + + +int mms_mmbox_delmsg(char *mmbox_root, char *user, Octstr *msgref) +{ + + Octstr *sdf = octstr_duplicate(msgref); + Octstr *fname = NULL, *home = user_mmbox_dir(mmbox_root,user); + Octstr *s = NULL; + int res = -1; + int ifd = -1, nifd; + + + octstr_replace(sdf, octstr_imm("-"), octstr_imm("/")); + + if (!home) + goto done; + + ifd = open_mmbox_index(octstr_get_cstr(home),1); + + if (ifd < 0) + goto done; + + fname = octstr_format("%S/%S", home, sdf); + + if ((nifd = update_mmbox_index(ifd, octstr_get_cstr(home), ITEM_DEL, sdf, NULL, NULL)) < 0) { + + error(0, "mmbox.del: failed to update index file, home is %s!", + octstr_get_cstr(home)); + goto done; + } + unlink(octstr_get_cstr(fname)); + ifd = nifd; + + res = 0; + done: + if (ifd > 0) + close(ifd); + + if (fname) + octstr_destroy(fname); + + if (s) + octstr_destroy(s); + if (home) + octstr_destroy(home); + + return 0; +} + +static int string_in_list(Octstr *s, List *l) +{ + int i, n; + + for (i = 0, n = list_len(l); i= start && ct <= limit) { + Octstr *x = octstr_create(idx); + octstr_replace(x, octstr_imm("/"), octstr_imm("-")); + list_append(dflist, x); + } + ct++; + if (xflags) + list_destroy(xflags, (list_item_destructor_t *)octstr_destroy); + } + + done: + if (fp) + fclose(fp); + else if (tmpfd) + close(tmpfd); + + if (ifd > 0) + close(ifd); + + if (flags) + list_destroy(flags, (list_item_destructor_t *)octstr_destroy); + + if (home) + octstr_destroy(home); + + return dflist; +} + +MmsMsg *mms_mmbox_get(char *mmbox_root, char *user, Octstr *msgref) +{ + Octstr *sdf = octstr_duplicate(msgref); + Octstr *fname = NULL, *home = user_mmbox_dir(mmbox_root,user); + Octstr *s = NULL; + int ifd = -1; + MmsMsg *m = NULL; + + + octstr_replace(sdf, octstr_imm("-"), octstr_imm("/")); + + if (!home) + goto done; + + ifd = open_mmbox_index(octstr_get_cstr(home),1); /* Grab a lock on the index file. */ + + if (ifd < 0) + goto done; + + fname = octstr_format("%S/%S", home, sdf); + s = octstr_read_file(octstr_get_cstr(fname)); + + if (s) + m = mms_frombinary(s, octstr_imm("anon@anon")); + + done: + if (ifd > 0) + close(ifd); + + if (fname) + octstr_destroy(fname); + + if (s) + octstr_destroy(s); + if (home) + octstr_destroy(home); + + return m; + +} diff --git a/mbuni/mmlib/mms_mmbox.h b/mbuni/mmlib/mms_mmbox.h new file mode 100644 index 0000000..ac0c665 --- /dev/null +++ b/mbuni/mmlib/mms_mmbox.h @@ -0,0 +1,14 @@ +#ifndef __MMS_MMBOX__INCLUDED__ +#define __MMS_MMBOX__INCLUDED__ +#include "mms_msg.h" +/* Initialise the root of the mmbox. Should be called once from load settings. */ +int mmbox_root_init(char *mmbox_root); +Octstr *mms_mmbox_addmsg(char *mmbox_root, char *user, MmsMsg *msg, Octstr *dfltstate); +int mms_mmbox_modmsg(char *mmbox_root, char *user, Octstr *msgref, + Octstr *state, List *flag_cmds); +int mms_mmbox_delmsg(char *mmbox_root, char *user, Octstr *msgref); +List *mms_mmbox_search(char *mmbox_root, char *user, + List *state, List *flag_cmds, int start, int limit); + +MmsMsg *mms_mmbox_get(char *mmbox_root, char *user, Octstr *msgref); +#endif diff --git a/mbuni/mmlib/mms_msg.c b/mbuni/mmlib/mms_msg.c index 4c1bb1c..a3c9c37 100644 --- a/mbuni/mmlib/mms_msg.c +++ b/mbuni/mmlib/mms_msg.c @@ -25,7 +25,7 @@ static void mm_destroy(MIMEEntity *mx); static inline void pack_short_integer(Octstr *s, int ch) { - unsigned long c = ch&0x7f; + unsigned long c = ((unsigned)ch)&0x7f; wsp_pack_short_integer(s, c); } @@ -741,15 +741,15 @@ static void mms_pack_well_known_field(Octstr *os, int field_type, Octstr *value) int i = 1; ch = octstr_get_char(value, 0); - if (ch == '-') - wsp_pack_short_integer(encoded, 0x81); + if (ch == '+') + pack_short_integer(encoded, 0x80); + else if (ch == '-') + pack_short_integer(encoded, 0x81); else if (ch == '/') - wsp_pack_short_integer(encoded, 0x82); - else if (ch == '+') /* Missing, or '+' ..*/ - wsp_pack_short_integer(encoded, 0x80); + pack_short_integer(encoded, 0x82); else { i = 0; - wsp_pack_short_integer(encoded, 0x80); + pack_short_integer(encoded, 0x82); /* default is filter. */ } s = octstr_copy(value, i, octstr_len(value)); wsp_pack_text(encoded, s); @@ -1502,6 +1502,18 @@ int mms_replace_header_value(MmsMsg *msg, char *hname, char *value) return 0; } +int mms_replace_header_values(MmsMsg *msg, char *hname, List *value) +{ + int i; + http_header_remove_all(msg->headers, hname); + + for (i = 0; i < list_len(value); i++) { + Octstr *x = list_get(value, i); + http_header_add(msg->headers, hname, octstr_get_cstr(x)); + } + return 0; +} + Octstr *mms_get_header_value(MmsMsg *msg, Octstr *header) { @@ -1510,6 +1522,25 @@ Octstr *mms_get_header_value(MmsMsg *msg, Octstr *header) } +List *mms_get_header_values(MmsMsg *msg, Octstr *header) +{ + List *h = http_header_find_all(msg->headers, octstr_get_cstr(header)); + List *l = list_create(); + int i; + + for (i = 0; i < list_len(h); i++) { + Octstr *hname, *value; + + http_header_get(h, i, &hname, &value); + + list_append(l, value); + octstr_destroy(hname); + } + http_destroy_headers(h); + return l; +} + + int mms_convert_readrec2readorig(MmsMsg *msg) { if (msg->message_type != MMS_MSGTYPE_READ_REC_IND) diff --git a/mbuni/mmlib/mms_msg.h b/mbuni/mmlib/mms_msg.h index 9780315..484887f 100644 --- a/mbuni/mmlib/mms_msg.h +++ b/mbuni/mmlib/mms_msg.h @@ -49,8 +49,14 @@ extern MmsMsg *mms_notification(MmsMsg *msg, unsigned int msize, MmsMsg *mms_retrieveconf(MmsMsg *msg, Octstr *transactionid, char *err, char *errtxt, Octstr *opt_from); int mms_remove_headers(MmsMsg *m, char *name); MmsMsg *mms_sendconf(char *errstr, char *msgid, char *transid, int isforward); + Octstr *mms_get_header_value(MmsMsg *msg, Octstr *header); + +/* Returns a list of values for the header given. */ +List *mms_get_header_values(MmsMsg *msg, Octstr *header); + int mms_replace_header_value(MmsMsg *msg, char *hname, char *value); +int mms_replace_header_values(MmsMsg *msg, char *hname, List *values); int mms_convert_readrec2readorig(MmsMsg *msg); diff --git a/mbuni/mmlib/mms_queue.c b/mbuni/mmlib/mms_queue.c index 2df64da..5ba8b65 100644 --- a/mbuni/mmlib/mms_queue.c +++ b/mbuni/mmlib/mms_queue.c @@ -22,47 +22,6 @@ static int free_envelope(MmsEnvelope *e, int removefromqueue); -/* - * lockfile: tries to lock a file, returns 0 if success, errno (which could be +ve) otherwise. - * we use flock() - */ -static int lockfile(int fd, int shouldblock) -{ - int n, stop; - unsigned flg = shouldblock ? 0 : LOCK_NB; - - do { - n = flock(fd, LOCK_EX|flg); - if (n < 0) { - if (errno == EINTR) - stop = 0; - else - stop = 1; - } else - stop = 1; - } while (!stop); - - return (n == 0) ? 0 : errno; -} - -static int check_lock(int fd, char *fname) -{ - struct stat fs = {0}, ds = {0}; - - - if (fstat(fd, &ds) < 0 || - stat(fname, &fs) < 0 || - - ds.st_nlink != fs.st_nlink || - memcmp(&ds.st_dev,&fs.st_dev, sizeof ds.st_dev) != 0 || - memcmp(&ds.st_ino,&fs.st_ino, sizeof ds.st_ino) != 0 || - ds.st_uid != fs.st_uid || - ds.st_gid != fs.st_gid || - ds.st_size != fs.st_size) - return -1; - else - return 0; -} /* Queue file structure: * - File consists of a series of lines, each line begins with a single letter, followed by * a parameter. Letters mean: @@ -115,19 +74,15 @@ MmsEnvelope *mms_queue_readenvelope(char *qf, char *mms_queuedir, int shouldbloc int okfile = 0; fname = octstr_format( "%.128s/%s", mms_queuedir, qf); - + if ((fd = open(octstr_get_cstr(fname), O_RDONLY)) < 0) { octstr_destroy(fname); return NULL; - } - - if (lockfile(fd, shouldblock) != 0 || - check_lock(fd, octstr_get_cstr(fname)) != 0) { + } else if (mm_lockfile(fd, octstr_get_cstr(fname), shouldblock) != 0) { close(fd); octstr_destroy(fname); - return NULL; + return NULL; } - e = gw_malloc(sizeof *e); memset(e, 0, sizeof *e); /* Clear it all .*/ @@ -277,8 +232,7 @@ static int writeenvelope(MmsEnvelope *e, int newenv) res = -1; goto done; - } else if (lockfile(fd, 0) != 0 || - check_lock(fd, octstr_get_cstr(tfname)) != 0) { /* Lock it. */ + } else if (mm_lockfile(fd, octstr_get_cstr(tfname), 0) != 0) { /* Lock it. */ error(0, "mms_queueadd: Failed lock temp file %s: error = %s\n", octstr_get_cstr(tfname), strerror(errno)); res = -1; @@ -423,8 +377,7 @@ static int mkqf(char qf[32], char *mms_queuedir) ctmp = octstr_get_cstr(tmp); fd = open(ctmp, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP); if (fd >= 0 && - (lockfile(fd,1) != 0 || - check_lock(fd, ctmp) != 0)) { + mm_lockfile(fd,ctmp,1) != 0) { unlink(ctmp); close(fd); fd = -1; diff --git a/mbuni/mmlib/mms_queue.h b/mbuni/mmlib/mms_queue.h index 1c5ec87..605168a 100644 --- a/mbuni/mmlib/mms_queue.h +++ b/mbuni/mmlib/mms_queue.h @@ -1,7 +1,8 @@ -#ifndef _MMSQUEUE_INCLUDED__ -#define _MMSQUEUE_INCLUDED__ +#ifndef _MMS_QUEUE_INCLUDED__ +#define _MMS_QUEUE_INCLUDED__ #include "mms_msg.h" +#include "mms_util.h" #define QFNAMEMAX 32 diff --git a/mbuni/mmlib/mms_util.c b/mbuni/mmlib/mms_util.c index bb0e27b..f6061cf 100644 --- a/mbuni/mmlib/mms_util.c +++ b/mbuni/mmlib/mms_util.c @@ -1,8 +1,15 @@ +#include #include #include #include #include #include + +#include +#include +#include +#include + #include "mms_util.h" #include "mms_uaprof.h" @@ -83,7 +90,8 @@ MmsBoxSettings *mms_load_mmsbox_settings(Cfg *cfg) m->global_queuedir = cfg_getx(grp, octstr_imm("send-queue-directory")); m->mm1_queuedir = cfg_getx(grp, octstr_imm("mm1-queue-directory")); m->mm4_queuedir = cfg_getx(grp, octstr_imm("mm4-queue-directory")); - + m->mmbox_rootdir = cfg_getx(grp, octstr_imm("mmbox-root-directory")); + if (cfg_get_integer(&m->maxsendattempts, grp, octstr_imm("maximum-send-attempts")) == -1) m->maxsendattempts = MAXQTRIES; @@ -202,6 +210,10 @@ MmsBoxSettings *mms_load_mmsbox_settings(Cfg *cfg) cfg_get_bool(&m->allow_ip_type, grp, octstr_imm("allow-ip-type")); cfg_get_bool(&m->optimize_notification_size, grp, octstr_imm("optimize-notification-size")); + + if (mmbox_root_init(octstr_get_cstr(m->mmbox_rootdir)) != 0) + warning(0, "Failed to initialise mmbox root directory, error: %s!", + strerror(errno)); return m; } @@ -937,3 +949,53 @@ void mms_log(char *logmsg, Octstr *from, List *to, octstr_destroy(xto); } + +static int lockfile(int fd, int shouldblock) +{ + int n, stop; + unsigned flg = shouldblock ? 0 : LOCK_NB; + + do { + n = flock(fd, LOCK_EX|flg); + if (n < 0) { + if (errno == EINTR) + stop = 0; + else + stop = 1; + } else + stop = 1; + } while (!stop); + + return (n == 0) ? 0 : errno; +} + +static int check_lock(int fd, char *fname) +{ + struct stat fs = {0}, ds = {0}; + + /* You might grab a lock on a file, but the file + * might be changed just before you grabbed the lock. Detect that and fail.. + */ + if (fstat(fd, &ds) < 0 || + stat(fname, &fs) < 0 || + + ds.st_nlink != fs.st_nlink || + memcmp(&ds.st_dev,&fs.st_dev, sizeof ds.st_dev) != 0 || + memcmp(&ds.st_ino,&fs.st_ino, sizeof ds.st_ino) != 0 || + ds.st_uid != fs.st_uid || + ds.st_gid != fs.st_gid || + ds.st_size != fs.st_size) + return -1; + else + return 0; +} + +int mm_lockfile(int fd, char *fname, int shouldblock) +{ + int ret = lockfile(fd,shouldblock); + + if (ret != 0 || + (ret = check_lock(fd,fname)) != 0) + return ret; + return 0; +} diff --git a/mbuni/mmlib/mms_util.h b/mbuni/mmlib/mms_util.h index 9076ecf..155f306 100644 --- a/mbuni/mmlib/mms_util.h +++ b/mbuni/mmlib/mms_util.h @@ -1,5 +1,5 @@ -#ifndef __MMS_GLOBAL__INCLUDED__ -#define __MMS_GLOBAL__INCLUDED__ +#ifndef __MMS_UTIL__INCLUDED__ +#define __MMS_UTIL__INCLUDED__ #include "gwlib/gwlib.h" #include "gwlib/mime.h" @@ -10,6 +10,7 @@ #include "mms_billing.h" #include "mms_resolve.h" #include "mms_detokenize.h" +#include "mms_mmbox.h" /* Send errors */ #define MMS_SEND_OK 0 @@ -36,6 +37,7 @@ typedef struct MmsBoxSettings { Octstr *unified_prefix, *local_prefix; Octstr *sendmail; Octstr *global_queuedir, *mm1_queuedir, *mm4_queuedir; + Octstr *mmbox_rootdir; Octstr *ua_profile_cache_dir; @@ -79,7 +81,7 @@ typedef struct MmsBoxSettings { Octstr *mms_notify_txt; Octstr *mms_notify_unprov_txt; Octstr *mms_toolarge; - Octstr *mmbox_host; + Octstr *mmbox_host; /* XXX need to remove this. */ Octstr *mms_email_txt; Octstr *mms_email_html; @@ -160,11 +162,20 @@ void mms_log(char *logmsg, Octstr *from, List *to, int msize, Octstr *msgid, Octstr *acct, Octstr *viaproxy, - char *interface, Octstr *ua); + char *interface, + Octstr *ua); void mms_log2(char *logmsg, Octstr *from, Octstr *to, int msize, Octstr *msgid, Octstr *acct, Octstr *viaproxy, - char *interface, Octstr *ua); + char *interface, + Octstr *ua); + +/* + * lockfile: tries to lock a file, returns 0 if success, errno (which could be +ve) otherwise. + * we use flock() + */ +int mm_lockfile(int fd, char *fname, int shouldblock); + #endif diff --git a/mbuni/mmsc/mmssend.c b/mbuni/mmsc/mmssend.c index 8e8ab00..eadaf03 100644 --- a/mbuni/mmsc/mmssend.c +++ b/mbuni/mmsc/mmssend.c @@ -3,11 +3,14 @@ #include "mms_queue.h" #include "mms_uaprof.h" #include "mms_util.h" +#include "mms_mmbox.h" static Octstr *data; static Octstr *from; static List *to; static MmsMsg *m; +static int savetommbox; +Octstr *mmbox; static MmsBoxSettings *settings; @@ -20,7 +23,10 @@ static int find_own(int i, int argc, char *argv[]) return 1; } else return -1; - else if (argv[i][1] == 't') + else if (argv[i][1] == 'b') { + savetommbox = 1; + return 0; + } else if (argv[i][1] == 't') if (i + 1 < argc) { int j, m; List *l = octstr_split(octstr_create(argv[i+1]), @@ -143,10 +149,51 @@ int main(int argc, char *argv[]) s = mms_queue_add(from, to, NULL, NULL, NULL, NULL, time(NULL), time(NULL) + settings->default_msgexpiry, m, NULL, 0, octstr_get_cstr(settings->global_queuedir)); + + if (savetommbox) + mmbox = mms_mmbox_addmsg(octstr_get_cstr(settings->mmbox_rootdir), + octstr_get_cstr(from), m, octstr_imm("Sent")); mms_log("Received", from, to, msize, s, NULL, NULL, "mmssend",NULL); - printf("Queued: %s\n", octstr_get_cstr(s)); + printf("Queued: %s, mmbox=%s\n", + octstr_get_cstr(s), mmbox ? octstr_get_cstr(mmbox) : ""); octstr_destroy(s); + +#if 0 + List *l = list_create(); + + list_append(l, octstr_imm("+testing")); + list_append(l, octstr_imm("-naughty")); + list_append(l, octstr_imm("+adult")); + list_append(l, octstr_imm("+adult")); + list_append(l, octstr_imm("+adult-2")); + int ret = mms_mmbox_modmsg(octstr_get_cstr(settings->mmbox_rootdir), + octstr_get_cstr(from), + octstr_imm("h-cs-df1111155064.1.x898915"), + octstr_imm("Draft"), l); + +#else + + List *l = list_create(); + List *sl = list_create(); + + +// list_append(l, octstr_imm("/naughty")); + + list_append(sl, octstr_imm("Draft")); + l = mms_mmbox_search(octstr_get_cstr(settings->mmbox_rootdir), + octstr_get_cstr(from), sl, l, -1, 2000); + + int ii; + + for (ii = 0; iimmbox_rootdir), + octstr_get_cstr(from), octstr_imm("h-cs-df1111155064.1.x898915")); + if (mm) + mms_msgdump(mm,1); +#endif return 0; }