static void kannel_parse_reply(SMSCConn *conn, Msg *msg, int status, List *headers, Octstr *body) { /* Test on three cases: * 1. an smsbox reply of an remote kannel instance * 2. an smsc_http response (if used for MT to MO looping) * 3. an smsbox reply of partly successful sendings */ if ((status == HTTP_OK || status == HTTP_ACCEPTED) && (octstr_case_compare(body, octstr_imm("0: Accepted for delivery")) == 0 || octstr_case_compare(body, octstr_imm("Sent.")) == 0 || octstr_case_compare(body, octstr_imm("Ok.")) == 0 || octstr_ncompare(body, octstr_imm("Result: OK"),10) == 0)) { char id[UUID_STR_LEN + 1]; Octstr *mid; /* create Octstr from UUID */ uuid_unparse(msg->sms.id, id); mid = octstr_create(id); /* add to our own DLR storage */ if (DLR_IS_ENABLED_DEVICE(msg->sms.dlr_mask)) dlr_add(conn->id, mid, msg, 0); octstr_destroy(mid); bb_smscconn_sent(conn, msg, NULL); } else { bb_smscconn_send_failed(conn, msg, SMSCCONN_FAILED_MALFORMED, octstr_duplicate(body)); } }
static int add_msg_cb(SMSCConn *conn, Msg *sms) { PrivData *privdata = conn->data; Msg *copy; copy = msg_duplicate(sms); /* * Send DLR if desired, which means first add the DLR entry * and then later find it and remove it. We need to ensure * that we put the DLR in first before producing the copy * to the list. */ if (DLR_IS_ENABLED_DEVICE(sms->sms.dlr_mask)) { Octstr *tmp; char id[UUID_STR_LEN + 1]; uuid_unparse(sms->sms.id, id); tmp = octstr_format("%s", id); dlr_add(conn->id, tmp, sms, 0); octstr_destroy(tmp); } gwlist_produce(privdata->outgoing_queue, copy); gwthread_wakeup(privdata->connection_thread); return 0; }
/****************************************************************************** * This function handles incoming operations. Used by both receiver and sender * threads (i.e. sender thread uses this function for delivery and ack * operations). * Returns 1 if successfull, otherwise 0 */ static int cgw_handle_op(SMSCConn *conn, Connection *server, struct cgwop *cgwop) { PrivData *privdata = conn->data; Msg *msg = NULL; Octstr *from, *app, *sid, *to, *msgtype, *msgdata; /* for messages */ Octstr *msid, *status, *txt; /* delivery reports */ Octstr *clid; /* for acks */ struct cgwop *reply = NULL; long trn, stat; /* transaction number for ack */ Msg *dlrmsg = NULL, *origmsg = NULL; Octstr *ts; if (cgwop == NULL) return 0; from = cgwop_get(cgwop, octstr_imm("from")); app = cgwop_get(cgwop, octstr_imm("app")); sid = cgwop_get(cgwop, octstr_imm("session-id")); to = cgwop_get(cgwop, octstr_imm("to")); msgtype = cgwop_get(cgwop, octstr_imm("type")); msgdata = cgwop_get(cgwop, octstr_imm("msg")); txt = cgwop_get(cgwop, octstr_imm("txt")); msid = cgwop_get(cgwop, octstr_imm("msid")); status = cgwop_get(cgwop, octstr_imm("status")); clid = cgwop_get(cgwop, octstr_imm("client-id")); if (clid != NULL) { octstr_parse_long(&trn, clid, 0, 10); if ((trn < 0) || (trn >= CGW_TRN_MAX)) { /* invalid transaction number */ info(0, "cgw: Invalid transaction number: %d", (int) trn); trn = -1; return 0; } } switch (cgwop->op) { case CGW_OP_MSG: msg = msg_create(sms); time(&msg->sms.time); msg->sms.msgdata = cgw_decode_msg(octstr_duplicate(msgdata)); msg->sms.sender = octstr_duplicate(from); msg->sms.receiver = octstr_duplicate(to); msg->sms.smsc_id = octstr_duplicate(conn->id); bb_smscconn_receive(conn, msg); reply = cgwop_create(CGW_OP_OK, -1); cgwop_add(reply, octstr_imm("session-id"), sid); cgwop_send(server, reply); /* send reply */ cgwop_destroy(reply); break; case CGW_OP_DELIVERY: if (privdata->dlr[trn]) { octstr_parse_long(&stat, status, 0, 10); origmsg = privdata->sendmsg[trn]; if (origmsg == NULL) break; ts = octstr_create(""); octstr_append(ts, conn->id); octstr_append_char(ts, '-'); octstr_append_decimal(ts, trn); switch (stat) { case 0: /* delivered */ dlrmsg = dlr_find(conn->id, ts, /* timestamp */ msid, /* destination */ DLR_SUCCESS); break; case 1: /* buffered */ dlrmsg = dlr_find(conn->id, ts, /* timestamp */ msid, /* destination */ DLR_BUFFERED); break; case 2: /* not delivered */ dlrmsg = dlr_find(conn->id, ts, /* timestamp */ msid, /* destination */ DLR_FAIL); break; } octstr_destroy(ts); if (dlrmsg != NULL) { dlrmsg->sms.msgdata = octstr_duplicate(txt); bb_smscconn_receive(conn, dlrmsg); } } break; case CGW_OP_OK: if (trn == -1) break; /* invalid transaction number */ /* info(0, "cgw: Got ACK: %s", octstr_get_cstr(clid)); */ privdata->sendtime[trn] = 0; privdata->unacked--; /* add delivery notification request if wanted */ msg = privdata->sendmsg[trn]; if (msg && msg->sms.dlr_url && DLR_IS_ENABLED_DEVICE(msg->sms.dlr_mask)) { Octstr *ts; ts = octstr_create(""); octstr_append(ts, conn->id); octstr_append_char(ts, '-'); octstr_append_decimal(ts, trn); dlr_add(conn->id, ts, msg); octstr_destroy(ts); privdata->dlr[trn] = 1; } else { privdata->dlr[trn] = 0; } /* mark as successfully sent */ bb_smscconn_sent(conn, msg, NULL); break; case CGW_OP_STATUS: info(0, "CGW: Warning: Got session status"); /* op:status messages are sent by ProviderServer to tell if there are problems with the session status. These are not wanted, and should never occur, as the delivery is cancelled, and no end-user billing is done. */ break; case CGW_OP_HELLO: info(0, "CGW: Server said: %s", octstr_get_cstr(cgwop_get(cgwop, octstr_imm("hello")))); break; case CGW_OP_ERR: if (trn == -1) break; /* invalid transaction number */ info(0, "CGW: Received error: %s", octstr_get_cstr(txt)); privdata->sendtime[trn] = 0; privdata->unacked--; bb_smscconn_send_failed(conn, privdata->sendmsg[trn], SMSCCONN_FAILED_REJECTED, octstr_create("REJECTED")); break; default: info(0, "cgw: Unknown operation: %d", cgwop->op); return 0; } return 1; }