[PATCH] Avoid bearerbox oom-kill!
Alexander Malysh <[email protected]>
| Newsgroups | gmane.comp.mobile.kannel.devel |
|---|---|
| Organization | Centrium GmbH |
| Message-ID | <[email protected]> |
Hi List, here is a small patch to avoid bearerbox oom-kill and give smsbox really status of sms. OOM-Kill simple scenario: your bearerbox is connected to SMSC but connection is broken (temporarely). So smsbox send sms to bearerbox (bbbox) and bbbox store it in queue (list) and sometimes is bbbox too large im mem (in worst case will be killed from kernel). Now you can define in config maximum-queue-length (applies for both queues) and bbbox send ack/nack to smsbox. For MO traffic I have added saying return codes , so each ptocol layer can use this (I beleave it's better as just -1 and protocol layer don't know why?) Comments? -- Mit besten Grüßen aus Köln Dipl.-Ing. Alexander Malysh ___________________________________________ Centrium GmbH Ehrenstraße 2 50672 Köln Fon: +49 (0221) 277 49 150 Fax: +49 (0221) 277 49 109 email: [email protected] web: www.centrium.de
avoid_oom.patch
(text/x-diff, 21.9 KB)
Index: gw/bb_boxc.c
===================================================================
RCS file: /home/cvs/gateway/gw/bb_boxc.c,v
retrieving revision 1.59
diff -a -u -r1.59 bb_boxc.c
--- gw/bb_boxc.c 14 Nov 2002 02:29:25 -0000 1.59
+++ gw/bb_boxc.c 15 Nov 2002 12:57:37 -0000
@@ -42,7 +42,7 @@
static List *smsbox_list = NULL;
/* dictionaries for holding the smsbox routing information */
-static Dict *smsbox_by_id = NULL;
+static Dict *smsbox_by_id = NULL;
static Dict *smsbox_by_smsc = NULL;
static Dict *smsbox_by_receiver = NULL;
@@ -56,7 +56,7 @@
static long boxid = 0;
-extern Mutex *boxid_mutex;
+extern Mutex *boxid_mutex;
typedef struct _boxc {
@@ -108,7 +108,7 @@
return NULL;
}
}
-
+
if (pack == NULL)
return NULL;
@@ -124,7 +124,8 @@
static void boxc_receiver(void *arg)
{
Boxc *conn = arg;
- Msg *msg;
+ Msg *msg, *mack;
+ int rc;
/* remove messages from socket until it is closed */
while (bb_status != BB_DEAD && conn->alive) {
@@ -133,35 +134,49 @@
msg = read_from_box(conn);
- if (msg == NULL) { /* garbage/connection lost */
- conn->alive = 0;
- break;
- }
-
- if (msg_type(msg) == sms && conn->is_wap == 0) {
- debug("bb.boxc", 0, "boxc_receiver: sms received");
+ if (msg == NULL) { /* garbage/connection lost */
+ conn->alive = 0;
+ break;
+ }
- /*
- * XXX save modifies ID, so if the smsbox uses it, save
- * it FIRST for the reply message!!!
- */
- store_save(msg);
- if (smsc2_rout(msg)== -1) {
- warning(0, "Message rejected by bearerbox, no router!");
- /* send NACK */
- bb_smscconn_send_failed(NULL, msg, SMSCCONN_FAILED_DISCARDED);
- }
- if (msg->sms.sms_type == mt_push) {
- /*
- * XXX generate ack-message and send it - in fact, this
- * should include information did it succeed, wa sit queued
- * or rejected...
- */
- }
+ if (msg_type(msg) == sms && conn->is_wap == 0) {
+ debug("bb.boxc", 0, "boxc_receiver: sms received");
+ /* save modifies ID, so if the smsbox uses it, save
+ * it FIRST for the reply message!!!
+ * generate ack-message and send it - in fact, this
+ * should include information did it succeed, wa sit queued
+ * or rejected...
+ */
+ mack = msg_create(ack);
+ mack->ack.id = msg->sms.id;
+ mack->ack.time = msg->sms.time;
+ store_save(msg);
+ rc = smsc2_rout(msg);
+ switch (rc) {
+ case -1:
+ warning(0, "Message rejected by bearerbox, no router !");
+ /* send NACK */
+ bb_smscconn_send_failed(NULL, msg, SMSCCONN_FAILED_DISCARDED);
+ mack->ack.nack = ack_failed;
+ break;
+ case -2:
+ warning(0, "Message rejected by bearerbox, queue full !");
+ /* send NACK */
+ bb_smscconn_send_failed(NULL, msg, SMSCCONN_FAILED_DISCARDED);
+ mack->ack.nack = ack_failed_tmp;
+ break;
+ case 0:
+ mack->ack.nack = ack_buffered;
+ break;
+ case 1:
+ mack->ack.nack = ack_success;
+ break;
+ }
+ list_produce(conn->incoming, mack);
} else if (msg_type(msg) == wdp_datagram && conn->is_wap) {
debug("bb.boxc", 0, "boxc_receiver: got wdp from wapbox");
-
+
list_produce(conn->outgoing, msg);
} else if (msg_type(msg) == sms && conn->is_wap) {
@@ -189,10 +204,10 @@
else if (msg_type(msg) == admin && msg->admin.command == cmd_identify) {
List *newlist;
- /* and add the boxc_ud into conn for boxc_status() output */
+ /* and add the boxc_id into conn for boxc_status() output */
if (conn->boxc_id == NULL)
conn->boxc_id = octstr_duplicate(msg->admin.boxc_id);
- /*
+ /*
* re-link the incoming queue for this connection to an independent
*/
newlist = list_create();
@@ -200,7 +215,7 @@
conn->incoming = newlist;
conn->retry = newlist;
- /* add this identified smsbox to the dictionary */
+ /* add this identified smsbox to the dictionary */
dict_put(smsbox_by_id, msg->admin.boxc_id, conn);
debug("bb.boxc", 0, "boxc_receiver: got boxc_id <%s> from <%s>",
octstr_get_cstr(msg->admin.boxc_id),
@@ -211,7 +226,7 @@
"ignored", octstr_get_cstr(conn->client_ip));
msg_destroy(msg);
}
- }
+ }
}
@@ -268,10 +283,10 @@
list_produce(conn->retry, msg);
break;
}
- if (send_msg(conn, msg) == -1) {
+ if (send_msg(conn, msg) == -1) {
/* if we fail to send, return msg to the list it came from
* before dying off */
- list_produce(conn->retry, msg);
+ list_produce(conn->retry, msg);
break;
}
msg_destroy(msg);
@@ -292,12 +307,12 @@
static Boxc *boxc_create(int fd, Octstr *ip, int ssl)
{
Boxc *boxc;
-
+
boxc = gw_malloc(sizeof(Boxc));
boxc->is_wap = 0;
boxc->load = 0;
boxc->conn = conn_wrap_fd(fd, ssl);
- mutex_lock(boxid_mutex);
+ mutex_lock(boxid_mutex);
boxc->id = boxid++;
mutex_unlock(boxid_mutex);
boxc->client_ip = ip;
@@ -305,13 +320,13 @@
boxc->connect_time = time(NULL);
boxc->boxc_id = NULL;
return boxc;
-}
+}
static void boxc_destroy(Boxc *boxc)
{
if (boxc == NULL)
return;
-
+
/* do nothing to the lists, as they are only references */
if (boxc->conn)
@@ -319,7 +334,7 @@
octstr_destroy(boxc->client_ip);
octstr_destroy(boxc->boxc_id);
gw_free(boxc);
-}
+}
@@ -348,7 +363,7 @@
return NULL;
}
newconn = boxc_create(newfd, ip, ssl);
-
+
/*
* check if the SSL handshake was successfull, otherwise
* this is no valid box connection any more
@@ -362,7 +377,7 @@
info(0, "Client connected from <%s> using SSL", octstr_get_cstr(ip));
else
info(0, "Client connected from <%s>", octstr_get_cstr(ip));
-
+
/* XXX TODO: do the hand-shake, baby, yeah-yeah! */
@@ -376,7 +391,7 @@
int fd;
Boxc *newconn;
long sender;
-
+
list_add_producer(flow_threads);
fd = (int)arg;
newconn = accept_boxc(fd, smsbox_port_ssl);
@@ -387,7 +402,7 @@
newconn->incoming = incoming_sms;
newconn->retry = incoming_sms;
newconn->outgoing = outgoing_sms;
-
+
list_append(smsbox_list, newconn);
sender = gwthread_create(boxc_sender, newconn);
@@ -402,7 +417,7 @@
gwthread_join(sender);
-cleanup:
+cleanup:
if (newconn->boxc_id) {
dict_remove(smsbox_by_id, newconn->boxc_id);
while (list_producer_count(newconn->incoming) > 0)
@@ -461,7 +476,7 @@
boxc_receiver(newconn);
/* cleanup after receiver has exited */
-
+
list_remove_producer(newconn->outgoing);
list_lock(wapbox_list);
list_delete_equal(wapbox_list, newconn);
@@ -471,7 +486,7 @@
list_remove_producer(newlist);
newconn->alive = 0;
-
+
gwthread_join(sender);
cleanup:
@@ -503,7 +518,7 @@
{
AddrPar *addr = ap;
Msg *msg = ms;
-
+
if (msg->wdp_datagram.source_port == addr->port &&
octstr_compare(msg->wdp_datagram.source_address, addr->address)==0)
return 1;
@@ -525,7 +540,7 @@
AddrPar *ap;
Boxc *conn, *best;
int i, b, len;
-
+
ap = list_search(route_info, msg, cmp_route);
if (ap == NULL) {
debug("bb.boxc", 0, "Did not find previous routing info for WDP, "
@@ -558,7 +573,7 @@
}
conn = best;
conn->load++; /* simulate new client until we get new values */
-
+
ap = gw_malloc(sizeof(AddrPar));
ap->address = octstr_duplicate(msg->wdp_datagram.source_address);
ap->port = msg->wdp_datagram.source_port;
@@ -600,7 +615,7 @@
route_info = list_create();
-
+
while(bb_status != BB_DEAD) {
list_consume(suspended); /* block here if suspended */
@@ -642,13 +657,13 @@
-static void wait_for_connections(int fd, void (*function) (void *arg),
+static void wait_for_connections(int fd, void (*function) (void *arg),
List *waited)
{
fd_set rf;
struct timeval tv;
int ret;
-
+
while(bb_status != BB_DEAD) {
/* XXX: if we are being shutdowned, as long as there is
@@ -663,7 +678,7 @@
FD_ZERO(&rf);
tv.tv_sec = 1;
tv.tv_usec = 0;
-
+
if (bb_status != BB_SUSPENDED)
FD_SET(fd, &rf);
@@ -689,8 +704,8 @@
list_add_producer(flow_threads);
gwthread_wakeup(MAIN_THREAD_ID);
port = (int)arg;
-
- fd = make_server_socket(port, NULL);
+
+ fd = make_server_socket(port, NULL);
/* XXX add interface_name if required */
if (fd < 0) {
@@ -726,7 +741,7 @@
smsbox_by_smsc = NULL;
dict_destroy(smsbox_by_receiver);
smsbox_by_receiver = NULL;
-
+
list_remove_producer(flow_threads);
}
@@ -738,7 +753,7 @@
list_add_producer(flow_threads);
gwthread_wakeup(MAIN_THREAD_ID);
port = (int)arg;
-
+
fd = make_server_socket(port, NULL);
/* XXX add interface_name if required */
@@ -924,7 +939,7 @@
if (gwthread_create(wdp_to_wapboxes, NULL) == -1)
panic(0, "Failed to start a new thread for wapbox routing");
-
+
if (gwthread_create(wapboxc_run, (void *)wapbox_port) == -1)
panic(0, "Failed to start a new thread for wapbox connections");
Index: gw/bb_smscconn.c
===================================================================
RCS file: /home/cvs/gateway/gw/bb_smscconn.c,v
retrieving revision 1.54
diff -a -u -r1.54 bb_smscconn.c
--- gw/bb_smscconn.c 14 Nov 2002 02:29:25 -0000 1.54
+++ gw/bb_smscconn.c 15 Nov 2002 12:57:37 -0000
@@ -65,7 +65,7 @@
static void log_sms(SMSCConn *conn, Msg *sms, char *message)
{
Octstr *text, *udh;
-
+
text = sms->sms.msgdata ? octstr_duplicate(sms->sms.msgdata) : octstr_create("");
udh = sms->sms.udhdata ? octstr_duplicate(sms->sms.udhdata) : octstr_create("");
if ((sms->sms.coding == DC_8BIT || sms->sms.coding == DC_UCS2))
@@ -123,22 +123,22 @@
void bb_smscconn_sent(SMSCConn *conn, Msg *sms)
{
Msg *mack;
-
+
counter_increase(outgoing_sms_counter);
if (conn) counter_increase(conn->sent);
-
+
/* write ACK to store file */
mack = msg_create(ack);
mack->ack.nack = 0;
mack->ack.time = sms->sms.time;
mack->ack.id = sms->sms.id;
-
+
(void) store_save(mack);
msg_destroy(mack);
-
+
/* XXX relay confirmancy message should be generated here */
-
+
log_sms(conn, sms, "Sent SMS");
msg_destroy(sms);
}
@@ -147,7 +147,7 @@
void bb_smscconn_send_failed(SMSCConn *conn, Msg *sms, int reason)
{
Msg *mnack;
-
+
switch (reason) {
case SMSCCONN_FAILED_SHUTDOWN:
@@ -165,41 +165,37 @@
(void) store_save(mnack);
msg_destroy(mnack);
-
+
if (conn) counter_increase(conn->failed);
if (reason == SMSCCONN_FAILED_DISCARDED)
log_sms(conn, sms, "DISCARDED SMS");
else
log_sms(conn, sms, "FAILED Send SMS");
msg_destroy(sms);
- }
-}
+ }
+}
-int bb_smscconn_receive(SMSCConn *conn, Msg *sms)
+long bb_smscconn_receive(SMSCConn *conn, Msg *sms)
{
char *uf;
/* do some queue control */
- if (maximum_queue_length != -1 && bb_status == BB_FULL &&
+ if (maximum_queue_length != -1 && bb_status == BB_FULL &&
list_len(incoming_sms) <= maximum_queue_length) {
bb_status = BB_RUNNING;
warning(0, "started to accept messages again");
}
-
- if (maximum_queue_length != -1 &&
+
+ if (maximum_queue_length != -1 &&
list_len(incoming_sms) > maximum_queue_length) {
if (bb_status != BB_FULL)
bb_status = BB_FULL;
warning(0, "incoming messages queue too long, dropping a message");
log_sms(conn, sms, "DROPPED Received SMS");
gwthread_sleep(0.1); /* letting the queue go down */
- return -1;
+ return SMSCCONN_FAILED_QFULL;
}
- /* else if (list_len(incoming_sms) > 100)
- * gwthread_sleep(0.5);
- */
-
if (unified_prefix == NULL)
uf = NULL;
else
@@ -213,7 +209,7 @@
octstr_get_cstr(sms->sms.sender));
log_sms(conn, sms, "REJECTED - not white-listed SMS");
msg_destroy(sms);
- return -1;
+ return SMSCCONN_FAILED_REJECTED;
}
if (black_list &&
numhash_find_number(black_list, sms->sms.sender) == 1) {
@@ -221,16 +217,16 @@
octstr_get_cstr(sms->sms.sender));
log_sms(conn, sms, "REJECTED - black-listed SMS");
msg_destroy(sms);
- return -1;
+ return SMSCCONN_FAILED_REJECTED;
}
if (sms->sms.sms_type != report)
sms->sms.sms_type = mo;
-
+
/* write to store (if enabled) */
if (store_save(sms) == -1)
- return -1;
-
+ return SMSCCONN_FAILED_TEMPORARILY;
+
if (sms->sms.sms_type != report)
log_sms(conn, sms, "Receive SMS");
else
@@ -247,7 +243,7 @@
counter_increase(incoming_sms_counter);
counter_increase(conn->received);
- return 0;
+ return SMSCCONN_SUCCESS;
}
@@ -256,7 +252,7 @@
*/
-
+
/* function to route outgoing SMS'es from delay-list
* use some nice magics to route them to proper SMSC
*/
@@ -264,18 +260,18 @@
{
Msg *msg, *newmsg, *startmsg;
int ret;
-
+
list_add_producer(flow_threads);
gwthread_wakeup(MAIN_THREAD_ID);
newmsg = startmsg = NULL;
ret = 0;
-
+
while(bb_status != BB_DEAD) {
if (newmsg == startmsg) {
if (ret != 1) {
- debug("bb.sms", 0, "sms_router: time to sleep");
+ debug("bb.sms", 0, "sms_router: time to sleep");
gwthread_sleep(600.0); /* hopefully someone wakes us up */
debug("bb.sms", 0, "sms_router: list_len = %ld",
list_len(outgoing_sms));
@@ -289,7 +285,7 @@
}
/* debug("bb.sms", 0, "sms_router: handling message (%p vs %p)",
* newmsg, startmsg); */
-
+
if (msg == NULL)
break;
@@ -299,12 +295,17 @@
bb_smscconn_send_failed(NULL, msg, SMSCCONN_FAILED_DISCARDED);
} else if (ret == 1) {
newmsg = startmsg = NULL;
+ } else if (ret == -2) {
+ /* bad found and outgoing queue is full, but not for us
+ * put message back in outgoing queue
+ */
+ list_produce(outgoing_sms, msg);
}
-
-
+
+
}
/* router has died, make sure that rest die, too */
-
+
smsc_running = 0;
list_remove_producer(flow_threads);
@@ -332,7 +333,7 @@
grp = cfg_get_single_group(cfg, octstr_imm("core"));
unified_prefix = cfg_get(grp, octstr_imm("unified-prefix"));
- if (cfg_get_integer(&maximum_queue_length, grp,
+ if (cfg_get_integer(&maximum_queue_length, grp,
octstr_imm("maximum-queue-length")) == -1)
maximum_queue_length = -1;
@@ -351,23 +352,23 @@
smsc_groups = cfg_get_multi_group(cfg, octstr_imm("smsc"));
/*
while(groups && (grp = list_extract_first(groups)) != NULL) {
- conn = smscconn_create(grp, 1);
+ conn = smscconn_create(grp, 1);
if (conn == NULL)
panic(0, "Cannot start with SMSC connection failing");
-
+
list_append(smsc_list, conn);
}
*/
list_add_producer(smsc_list);
- for (i = 0; i < list_len(smsc_groups) &&
+ for (i = 0; i < list_len(smsc_groups) &&
(grp = list_get(smsc_groups, i)) != NULL; i++) {
- conn = smscconn_create(grp, 1);
+ conn = smscconn_create(grp, 1);
if (conn == NULL)
panic(0, "Cannot start with SMSC connection failing");
list_append(smsc_list, conn);
}
list_remove_producer(smsc_list);
-
+
if ((router_thread = gwthread_create(sms_router, NULL)) == -1)
panic(0, "Failed to start a new thread for SMS routing");
@@ -437,14 +438,14 @@
octstr_get_cstr(id));
return -1;
}
-
+
list_delete(smsc_list, i, 1); /* drop it from the active smsc list */
smscconn_destroy(conn); /* destroy the connection */
/* find the group with smsc id */
grp = NULL;
list_lock(smsc_groups);
- for (i = 0; i < list_len(smsc_groups) &&
+ for (i = 0; i < list_len(smsc_groups) &&
(grp = list_get(smsc_groups, i)) != NULL; i++) {
smscid = cfg_get(grp, octstr_imm("smsc-id"));
if (smscid != NULL && octstr_compare(smscid, id) == 0) {
@@ -473,7 +474,7 @@
{
SMSCConn *conn;
int i;
-
+
for (i = 0; i < list_len(smsc_list); i++) {
conn = list_get(smsc_list, i);
smscconn_start(conn);
@@ -487,7 +488,7 @@
{
SMSCConn *conn;
int i;
-
+
list_lock(smsc_list);
for (i = 0; i < list_len(smsc_list); i++) {
conn = list_get(smsc_list, i);
@@ -578,14 +579,14 @@
tmp = octstr_format("%sSMSC connections:%s", para ? "<p>" : "", lb);
else
tmp = octstr_format("<smscs><count>%d</count>\n\t", list_len(smsc_list));
-
+
list_lock(smsc_list);
for (i = 0; i < list_len(smsc_list); i++) {
conn = list_get(smsc_list, i);
if ((smscconn_info(conn, &info) == -1)) {
- /*
- * we do not delete SMSCs from the list
+ /*
+ * we do not delete SMSCs from the list
* this way we can show in the status which links are dead
*/
continue;
@@ -603,7 +604,7 @@
octstr_append_cstr(tmp, " ");
octstr_append(tmp, conn_id);
octstr_append_cstr(tmp, " ");
- }
+ }
if (status_type == BBSTATUS_XML) {
octstr_append_cstr(tmp, "<smsc>\n\t\t<name>");
octstr_append(tmp, conn_name);
@@ -634,7 +635,7 @@
default:
sprintf(tmp3, "unknown");
}
-
+
if (status_type == BBSTATUS_XML)
octstr_format_append(tmp, "<status>%s</status>\n\t\t<received>%ld</received>"
"\n\t\t<sent>%ld</sent>\n\t\t<failed>%ld</failed>\n\t\t"
@@ -664,6 +665,8 @@
* If finds a good one, puts into it and returns 1
* If finds only bad ones, but acceptable, queues and
* returns 0 (like all acceptable currently disconnected)
+ * If found bad , but maximum_queue_length reached return -2
+ * and message is not destroyed.
* If cannot find nothing at all, returns -1 and
* message is NOT destroyed (otherwise it is)
*/
@@ -680,7 +683,7 @@
/* XXX handle ack here? */
if (msg_type(msg) != sms)
return -1;
-
+
if (list_len(smsc_list) == 0) {
warning(0, "No SMSCes to receive message");
return -1;
@@ -691,7 +694,7 @@
uf = unified_prefix ? octstr_get_cstr(unified_prefix) : NULL;
normalize_number(uf, &(msg->sms.receiver));
-
+
/* select in which list to add this
* start - from random SMSCConn, as they are all 'equal'
*/
@@ -701,7 +704,7 @@
s = gw_rand() % list_len(smsc_list);
best_preferred = best_ok = NULL;
bad_found = 0;
-
+
conn = NULL;
for (i=0; i < list_len(smsc_list); i++) {
conn = list_get(smsc_list, (i+s) % list_len(smsc_list));
@@ -711,10 +714,11 @@
continue;
/* if we already have a preferred one, skip non-preferred */
- if (ret != 1 && best_preferred)
+ if (ret != 1 && best_preferred)
continue;
smscconn_info(conn, &info);
+
/* If connection is not currently answering... */
if (info.status != SMSCCONN_ACTIVE) {
bad_found = 1;
@@ -739,8 +743,12 @@
else if (best_ok)
ret = smscconn_send(best_ok, msg);
else if (bad_found) {
- if (bb_status != BB_SHUTDOWN)
+ if (bb_status != BB_SHUTDOWN) {
+ if (maximum_queue_length != -1 && maximum_queue_length <= list_len(outgoing_sms)) {
+ return -2;
+ }
list_produce(outgoing_sms, msg);
+ }
return 0;
}
else {
Index: gw/bb_smscconn_cb.h
===================================================================
RCS file: /home/cvs/gateway/gw/bb_smscconn_cb.h,v
retrieving revision 1.9
diff -a -u -r1.9 bb_smscconn_cb.h
--- gw/bb_smscconn_cb.h 31 Aug 2001 19:54:47 -0000 1.9
+++ gw/bb_smscconn_cb.h 15 Nov 2002 12:57:37 -0000
@@ -41,19 +41,22 @@
void bb_smscconn_send_failed(SMSCConn *conn, Msg *sms, int reason);
enum {
+ SMSCCONN_SUCCESS = 0,
SMSCCONN_FAILED_SHUTDOWN,
SMSCCONN_FAILED_REJECTED,
SMSCCONN_FAILED_MALFORMED,
SMSCCONN_FAILED_TEMPORARILY,
- SMSCCONN_FAILED_DISCARDED
+ SMSCCONN_FAILED_DISCARDED,
+ SMSCCONN_FAILED_QFULL
};
/* called when a new message 'sms' received. Callback handles
- * 'sms' and MAY NOT be used by caller again. Return 0 if all went
- * fine, and -1 if bearerbox does NOT accept the 'sms' (black/white
- * -listed) */
-int bb_smscconn_receive(SMSCConn *conn, Msg *sms);
+ * 'sms' and MAY NOT be used by caller again. Return SMSCCONN_SUCCESS if all went
+ * fine, SMSCCONN_FAILED_QFULL if incoming queue full, SMSCCONN_FAILED_TEMPORARILY
+ * if store enabled and failed, and SMSCCONN_FAILED_REJECTED if bearerbox does
+ * NOT accept the 'sms' (black/whitelisted) */
+long bb_smscconn_receive(SMSCConn *conn, Msg *sms);
#endif
Index: gw/msg.h
===================================================================
RCS file: /home/cvs/gateway/gw/msg.h,v
retrieving revision 1.13
diff -a -u -r1.13 msg.h
--- gw/msg.h 14 Nov 2002 02:29:25 -0000 1.13
+++ gw/msg.h 15 Nov 2002 12:57:37 -0000
@@ -1,8 +1,8 @@
/*
* msg.h - declarations for message manipulation
- *
+ *
* This file declares the Msg data type and the functions to manipulate it.
- *
+ *
* Lars Wirzenius
*/
@@ -45,6 +45,14 @@
cmd_suspend = 1,
cmd_resume = 2,
cmd_identify = 3
+};
+
+/* ack message status */
+enum {
+ ack_success = 0,
+ ack_failed = 1, /* do not try again */
+ ack_failed_tmp = 2, /* temporary failed , try again */
+ ack_buffered = 3
};
/*