[PATCH] avoid bearerbox oom-kill (fix)
Alexander Malysh <[email protected]>
| Newsgroups | gmane.comp.mobile.kannel.devel |
|---|---|
| Organization | Centrium GmbH |
| Message-ID | <[email protected]> |
Hi, this is the same oom-kill patch with memleak bugfix. -- 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, 22.2 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 17:41:17 -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,42 +134,56 @@
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) {
debug("bb.boxc", 0, "boxc_receiver: got sms from wapbox");
store_save(msg);
- if (smsc2_rout(msg)== -1) {
+ if (smsc2_rout(msg) < 0) {
warning(0, "Message rejected by bearerbox, no router!");
msg_destroy(msg);
}
@@ -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 17:41:17 -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 17:41:17 -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 17:41:17 -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
};
/*