Hi,

The patch is based on snapshot version 20031105.

So tell me what do I need to do in order to get the patch committed?
Updated User manual?
Sample configuration files?

Cheers,
Phuah Yee Keat
diff -Naur kannel-snapshot/gw/smsc/smsc_cpa.c kannel-snapshot-cpa/gw/smsc/smsc_cpa.c
--- kannel-snapshot/gw/smsc/smsc_cpa.c  1970-01-01 07:30:00.000000000 +0730
+++ kannel-snapshot-cpa/gw/smsc/smsc_cpa.c      2004-01-14 11:42:29.000000000 +0800
@@ -0,0 +1,745 @@
+/*
+ * smsc_cpa.c - interface to DIGI CPA
+ *
+ * this file is copied and modified from smsc_http
+ * coz we need to add a couple of stuffs to the ConnData
+ * and a couple of additional configuration parameters too!
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <errno.h>
+#include <time.h>
+#include <limits.h>
+
+#include "gwlib/gwlib.h"
+#include "smscconn.h"
+#include "smscconn_p.h"
+#include "bb_smscconn_cb.h"
+#include "msg.h"
+#include "sms.h"
+#include "dlr.h"
+
+/****
+ * Start of CPA stuffs
+ ****/
+typedef struct {
+    HTTPCaller *http_ref;
+    long receive_thread;
+    long send_cb_thread;
+    long login_cb_thread;
+    long login_thread;
+    long http_result_thread;
+    int shutdown;
+    int        port;   /* port for receiving SMS'es */
+    Octstr *receive_host;
+    Octstr *allow_ip;
+    Octstr *send_url;
+    Octstr *login_url;
+    long open_sends;
+    Octstr *username;   /* if needed */
+    Octstr *password;   /* as said */
+    Octstr *cp_id;
+    Octstr *service_id;
+    Octstr *short_code;
+    Octstr *session_id;
+    Octstr *prepaid_price_code;
+    Octstr *postpaid_price_code;
+    Octstr *charge_party;
+    int elapse_time; /* number of minutes, before we need to relogin */
+    int logged_in;
+
+    int no_sender;      /* ditto */
+    int no_coding;      /* this, too */
+    int no_sep;         /* not to mention this */
+
+    /* callback functions set by HTTP-SMSC type */
+    void (*send_sms) (SMSCConn *conn, Msg *msg);
+    void (*parse_reply) (SMSCConn *conn, Msg *msg, int status,
+                         List *headers, Octstr *body);
+    void (*receive_sms) (SMSCConn *conn, HTTPClient *client,
+                         List *headers, Octstr *body, List *cgivars);
+} CPA;
+
+static void cpa_destroy(CPA *cpa)
+{
+    if (cpa == NULL)
+        return;
+    if (cpa->http_ref)
+        http_caller_destroy(cpa->http_ref);
+    octstr_destroy(cpa->receive_host);
+    octstr_destroy(cpa->allow_ip);
+    octstr_destroy(cpa->send_url);
+    octstr_destroy(cpa->login_url);
+    octstr_destroy(cpa->username);
+    octstr_destroy(cpa->password);
+    octstr_destroy(cpa->cp_id);
+    octstr_destroy(cpa->service_id);
+    octstr_destroy(cpa->short_code);
+    octstr_destroy(cpa->session_id);
+    octstr_destroy(cpa->prepaid_price_code);
+    octstr_destroy(cpa->postpaid_price_code);
+    octstr_destroy(cpa->charge_party);
+
+    gw_free(cpa);
+}
+
+typedef enum { TYPE_LOGIN, TYPE_SENDSMS } CPAType;
+
+typedef struct {
+    CPAType type;
+    /* here are a couple of stuffs, only to be used for the appropriate type */
+    Msg *msg;           /* type == TYPE_SENDSMS */
+} CPAResponse;
+
+static void send_login(CPA *cpa)
+{
+    Octstr *response_url;
+    List *headers;
+    CPAResponse *cpa_response;
+
+    response_url = octstr_format("http://%S:%d/login_rsp";, cpa->receive_host, 
cpa->port);
+    octstr_url_encode(response_url);
+
+    headers = http_create_empty_headers();
+    http_header_add(headers, "cpa_login_name", octstr_get_cstr(cpa->username));
+    http_header_add(headers, "cpa_password", octstr_get_cstr(cpa->password));
+    http_header_add(headers, "cpa_cp_id", octstr_get_cstr(cpa->cp_id));
+    http_header_add(headers, "cpa_cp_response_url", octstr_get_cstr(response_url));
+
+    cpa_response = gw_malloc(sizeof(CPAResponse));
+    cpa_response->type = TYPE_LOGIN;
+    cpa_response->msg = NULL;
+
+    http_start_request(cpa->http_ref, HTTP_METHOD_GET, cpa->login_url, headers, 
+                       NULL, 0, cpa_response, NULL);
+
+    octstr_destroy(response_url);
+    http_destroy_headers(headers);
+}
+
+static void cpa_http_receive_result(void *arg)
+{
+    SMSCConn *conn = arg;
+    CPA *cpa = conn->data;
+    int status;
+    List *headers;
+    Octstr *final_url, *body;
+    CPAResponse *cpa_response;
+
+    while (cpa->shutdown == 0) {
+        cpa_response = http_receive_result(cpa->http_ref, &status, 
+                &final_url, &headers, &body);
+
+        //http_header_dump(headers);
+
+        /* we have no use for these! clean them up so we can have mutliple exit 
points */
+        http_destroy_headers(headers);
+        octstr_destroy(final_url);
+        octstr_destroy(body);
+
+        if (cpa_response == NULL) {
+            break;
+        }
+
+        if (cpa->shutdown == 1) {
+            /* duh, we have waited too long, until we are supposed to shutdown! */
+            break;
+        }
+
+        if (status == -1) {
+            /* something is terribly wrong with the connection */
+            /* TODO : if we get status = -1 more than 3 times, declare disconnected 
and try to relogin */
+        }
+
+        switch (cpa_response->type) {
+            case TYPE_LOGIN:
+                if (status!=HTTP_OK) {
+                    error(0, "CPA[%s]: received http_status [%d] for login request",
+                            octstr_get_cstr(conn->id), status);
+                    conn->status = SMSCCONN_RECONNECTING;
+                    /* login_manager will relogin for us */
+                    cpa->logged_in = 0;
+                }  else {
+                    debug("smsc.cpa", 0, "CPA[%s]: received HTTP_OK for login 
request, "
+                            "but doesn't mean that we are successfully logged in!",
+                            octstr_get_cstr(conn->id));
+                }
+                break;
+            case TYPE_SENDSMS:
+                if (status!=HTTP_OK) {
+                    error(0, "CPA[%s]: received http_status [%d] for sendsms request",
+                            octstr_get_cstr(conn->id), status);
+
+                    /* 
+                     * be a bit gentle to the smsc, and sleep
+                     * this will block this whole thread, even the login_response
+                     * but what the heck, if the smsc is not replying HTTP_OK
+                     * something is terribly wrong with it! (probably some java 
error! keke)
+                     */
+                    gwthread_sleep(conn->reconnect_delay);
+                    debug("smsc.cpa", 0, "CPA[%s]: Re-queuing message",
+                        octstr_get_cstr(conn->id));
+
+                    bb_smscconn_send_failed(conn, cpa_response->msg, 
SMSCCONN_FAILED_TEMPORARILY, NULL);
+                } else {
+                    debug("smsc.cpa", 0, "CPA[%s]: received HTTP_OK for sendsms 
request, "
+                            "but doesn't mean that we have successfully sent the 
message!",
+                            octstr_get_cstr(conn->id));
+                    info(0, "CPA[%s]: since CPA did not send a usable id for matching 
sendsms request, "
+                            " we would have to settle for a sending success upon 
receving HTTP_OK, "
+                            " and just ignore the http_response!",
+                            octstr_get_cstr(conn->id));
+                    bb_smscconn_sent(conn, cpa_response->msg, NULL);
+                }
+                break;
+        }
+
+        gw_free(cpa_response);
+    }
+
+    debug("smsc.cpa", 0, "CPA[%s]: cpa_http_receive_result dying",
+          octstr_get_cstr(conn->id));
+    cpa->shutdown = 1;
+
+    if (cpa->open_sends) {
+        warning(0, "CPA[%s]: Shutdown while <%ld> requests are pending.",
+                octstr_get_cstr(conn->id), cpa->open_sends);
+    }
+
+    gwthread_join(cpa->receive_thread);
+
+    conn->data = NULL;
+    cpa_destroy(cpa);
+
+    conn->status = SMSCCONN_DEAD;
+    bb_smscconn_killed();
+}
+
+static void cpa_send_sms(SMSCConn *conn, Msg *sms)
+{
+    CPA *cpa = conn->data;
+    Octstr *response_url;
+    List *headers;
+    CPAResponse *cpa_response;
+
+    /* msg_dump(sms, 0); */
+    headers = list_create();
+
+    response_url = octstr_format("http://%S:%d/txn_rsp";, cpa->receive_host, 
cpa->port);
+
+    http_header_add(headers, "cpa_cp_id", octstr_get_cstr(cpa->cp_id));
+    http_header_add(headers, "cpa_cp_response_url", octstr_get_cstr(response_url));
+    http_header_add(headers, "cpa_cp_session_id", octstr_get_cstr(cpa->session_id));
+    http_header_add(headers, "cpa_short_code", octstr_get_cstr(cpa->short_code));
+
+    http_header_add(headers, "cpa_service_id", octstr_get_cstr(cpa->service_id));
+
+    /* sms push does not have transaction id */
+    /* XXX : does sms reply goes thru here also? if it does, we need to keep some 
states! */
+    http_header_add(headers, "cpa_transaction_id", "");
+
+    /* told by CPA to set the source_mobtel to destination_mobtel */
+    http_header_add(headers, "cpa_source_mobtel", octstr_get_cstr(sms->sms.receiver));
+    http_header_add(headers, "cpa_destination_mobtel", 
octstr_get_cstr(sms->sms.receiver));
+
+    http_header_add(headers, "cpa_charge_party", octstr_get_cstr(cpa->charge_party));
+
+    http_header_add(headers, "cpa_delivery_channel", "SMS");
+
+    http_header_add(headers, "cpa_prepaid_price_code", 
octstr_get_cstr(cpa->prepaid_price_code));
+    http_header_add(headers, "cpa_postpaid_price_code", 
octstr_get_cstr(cpa->postpaid_price_code));
+
+    http_header_add(headers, "cpa_interactive_push_session", "N");
+    http_header_add(headers, "cpa_terminate_interactive_sesion", "N");
+    http_header_add(headers, "cpa_status", "1");
+    http_header_add(headers, "cpa_content_sequence", "1");
+    http_header_add(headers, "cpa_max_content", "1");
+    http_header_add(headers, "cpa_content", octstr_get_cstr(sms->sms.msgdata));
+
+    debug("smsc.cpa", 0, "CPA[%s]: Start request",
+          octstr_get_cstr(conn->id));
+
+    cpa_response = gw_malloc(sizeof(CPAResponse));
+    cpa_response->type = TYPE_SENDSMS;
+    cpa_response->msg = msg_duplicate(sms);
+
+    //http_header_dump(headers);
+
+    http_start_request(cpa->http_ref, HTTP_METHOD_GET, cpa->send_url, headers, 
+                       NULL, 0, cpa_response, NULL);
+
+    octstr_destroy(response_url);
+    http_destroy_headers(headers);
+}
+
+static void cpa_receive_sms(SMSCConn *conn, HTTPClient *client,
+                              List *headers, Octstr *body, List *cgivars)
+{
+    CPA *cpa = conn->data;
+    Octstr *retmsg;
+    List *reply_headers;
+    Octstr *cpa_short_code, *cpa_keyword, *cpa_service_id, *cpa_transaction_id, 
*cpa_source_mobtel, *cpa_delivery_channel, *cpa_content, *cpa_sms_datacoding_id;
+    int ret;
+
+    //http_header_dump(headers);
+
+    cpa_short_code = http_header_value(headers, octstr_imm("cpa_short_code")); 
+    cpa_keyword = http_header_value(headers, octstr_imm("cpa_keyword")); 
+    cpa_service_id = http_header_value(headers, octstr_imm("cpa_service_id")); 
+    cpa_transaction_id = http_header_value(headers, 
octstr_imm("cpa_transaction_id")); 
+    cpa_source_mobtel = http_header_value(headers, octstr_imm("cpa_source_mobtel")); 
+    cpa_delivery_channel = http_header_value(headers, 
octstr_imm("cpa_delivery_channel")); 
+    cpa_content = http_header_value(headers, octstr_imm("cpa_content")); 
+    cpa_sms_datacoding_id = http_header_value(headers, 
octstr_imm("cpa_sms_datacoding_id")); 
+
+    /* dump the response, so we can see more clearly from the logs! ;^) */
+    debug("smsc.cpa", 0, "CPA receive_sms response dump:");
+    debug("smsc.cpa", 0, "  cpa_short_code: %s", octstr_get_cstr(cpa_short_code));
+    debug("smsc.cpa", 0, "  cpa_keyword: %s", octstr_get_cstr(cpa_keyword));
+    debug("smsc.cpa", 0, "  cpa_service_id: %s", octstr_get_cstr(cpa_service_id));
+    debug("smsc.cpa", 0, "  cpa_transaction_id: %s", 
octstr_get_cstr(cpa_transaction_id));
+    debug("smsc.cpa", 0, "  cpa_source_mobtel: %s", 
octstr_get_cstr(cpa_source_mobtel));
+    debug("smsc.cpa", 0, "  cpa_delivery_channel: %s", 
octstr_get_cstr(cpa_delivery_channel));
+    debug("smsc.cpa", 0, "  cpa_content: %s", octstr_get_cstr(cpa_content));
+    debug("smsc.cpa", 0, "  cpa_sms_datacoding_id: %s", 
octstr_get_cstr(cpa_sms_datacoding_id));
+    debug("smsc.cpa", 0, "CPA receive_sms response dump ends.");
+
+    Msg *msg;
+    msg = msg_create(sms);
+
+    msg->sms.sender = octstr_duplicate(cpa_source_mobtel);
+    /* assume that the receiver is the short code value */
+    msg->sms.receiver = octstr_duplicate(cpa_short_code);
+    msg->sms.msgdata = octstr_duplicate(cpa_content);
+
+    msg->sms.smsc_id = octstr_duplicate(conn->id);
+    msg->sms.time = time(NULL); 
+
+    ret = bb_smscconn_receive(conn, msg);
+
+    if (ret != SMSCCONN_SUCCESS) {
+        error(0, "CPA[%s]: bb_smscconn_receive failed.", octstr_get_cstr(conn->id));
+    }
+
+       retmsg = octstr_create("Ok.");
+
+    reply_headers = list_create();
+    http_header_add(reply_headers, "Content-Type", "text/plain");
+    debug("smsc.cpa", 0, "CPA[%s]: Sending reply",
+          octstr_get_cstr(conn->id));
+    http_send_reply(client, HTTP_OK, reply_headers, retmsg);
+
+    octstr_destroy(retmsg);
+    http_destroy_headers(reply_headers);
+
+    octstr_destroy(cpa_short_code);
+    octstr_destroy(cpa_keyword);
+    octstr_destroy(cpa_service_id);
+    octstr_destroy(cpa_transaction_id);
+    octstr_destroy(cpa_source_mobtel);
+    octstr_destroy(cpa_delivery_channel);
+    octstr_destroy(cpa_content);
+    octstr_destroy(cpa_sms_datacoding_id);
+}
+
+static void cpa_process_response(SMSCConn *conn, HTTPClient *client,
+                              List *headers, Octstr *body, List *cgivars)
+{
+    CPA *cpa = conn->data;
+    Octstr *retmsg;
+    Octstr *cpa_service_id, *cpa_transaction_id, *cpa_destination_mobtel, 
*cpa_charge_party, *cpa_status, *cpa_error_code;
+
+    List *reply_headers;
+
+    //http_header_dump(headers);
+
+    cpa_service_id = http_header_value(headers, octstr_imm("cpa_service_id")); 
+    cpa_transaction_id = http_header_value(headers, 
octstr_imm("cpa_transaction_id")); 
+    cpa_destination_mobtel = http_header_value(headers, 
octstr_imm("cpa_destination_mobtel")); 
+    cpa_charge_party = http_header_value(headers, octstr_imm("cpa_charge_party")); 
+    cpa_status = http_header_value(headers, octstr_imm("cpa_status")); 
+    cpa_error_code = http_header_value(headers, octstr_imm("cpa_error_code")); 
+
+    /* dump the response, so we can see more clearly from the logs! ;^) */
+    debug("smsc.cpa", 0, "CPA sendsms_response dump:");
+    debug("smsc.cpa", 0, "  cpa_service_id: %s", octstr_get_cstr(cpa_service_id));
+    debug("smsc.cpa", 0, "  cpa_transaction_id: %s", 
octstr_get_cstr(cpa_transaction_id));
+    debug("smsc.cpa", 0, "  cpa_destination_mobtel: %s", 
octstr_get_cstr(cpa_destination_mobtel));
+    debug("smsc.cpa", 0, "  cpa_charge_party: %s", octstr_get_cstr(cpa_charge_party));
+    debug("smsc.cpa", 0, "  cpa_status: %s", octstr_get_cstr(cpa_status));
+    debug("smsc.cpa", 0, "  cpa_error_code: %s", octstr_get_cstr(cpa_error_code));
+    debug("smsc.cpa", 0, "CPA sendsms_response dump ends.");
+
+    if (octstr_str_compare(cpa_status, "1")==0) {
+        info(0, "CPA[%s]: Message accepted", octstr_get_cstr(conn->id));
+    } else {
+        warning(0, "CPA[%s]: sendsms denied with status [%s] error_code [%s]", 
+                octstr_get_cstr(conn->id), 
+                octstr_get_cstr(cpa_status), 
+                octstr_get_cstr(cpa_error_code)); 
+    }
+
+       retmsg = octstr_create("Ok.");
+
+    reply_headers = list_create();
+    http_header_add(reply_headers, "Content-Type", "text/plain");
+    debug("smsc.cpa", 0, "CPA[%s]: Sending reply",
+          octstr_get_cstr(conn->id));
+    http_send_reply(client, HTTP_OK, reply_headers, retmsg);
+
+    octstr_destroy(retmsg);
+    http_destroy_headers(reply_headers);
+
+    octstr_destroy(cpa_service_id);
+    octstr_destroy(cpa_transaction_id);
+    octstr_destroy(cpa_destination_mobtel);
+    octstr_destroy(cpa_charge_party);
+    octstr_destroy(cpa_status);
+    octstr_destroy(cpa_error_code);
+}
+
+static void cpa_process_login_response(SMSCConn *conn, HTTPClient *client,
+                              List *headers, Octstr *body, List *cgivars)
+{
+    CPA *cpa = conn->data;
+    Octstr *retmsg;
+    Octstr *cpa_status, *cpa_error_code;
+    Octstr *tmp_string;
+    List *reply_headers;
+
+    cpa->session_id = http_header_value(headers, octstr_imm("cpa_cp_session_id")); 
+    if (!cpa->session_id) {
+        error(0, "session_id not found in login-rsp"); 
+    }
+
+    tmp_string = http_header_value(headers, 
octstr_imm("cpa_cp_session_elapse_time")); 
+    if(tmp_string) {
+           sscanf(octstr_get_cstr(tmp_string),"%d", &cpa->elapse_time);
+        octstr_destroy(tmp_string);
+    } else {
+        error(0, "elapse_time not found in login-rsp");
+    }
+
+    cpa_status = http_header_value(headers, octstr_imm("cpa_status")); 
+    cpa_error_code = http_header_value(headers, octstr_imm("cpa_error_code")); 
+
+    /* dump the response, so we can see more clearly from the logs! ;^) */
+    debug("smsc.cpa", 0, "CPA login response dump:");
+    debug("smsc.cpa", 0, "  cpa_cp_session_id: %s", octstr_get_cstr(cpa->session_id));
+    debug("smsc.cpa", 0, "  cpa_cp_session_elapse_time: %d", cpa->elapse_time);
+    debug("smsc.cpa", 0, "  cpa_status: %s", octstr_get_cstr(cpa_status));
+    debug("smsc.cpa", 0, "  cpa_error_code: %s", octstr_get_cstr(cpa_error_code));
+    debug("smsc.cpa", 0, "CPA login response dump ends.");
+
+    if (octstr_str_compare(cpa_status, "1")==0) {
+        info(0, "CPA[%s]: Login accepted", octstr_get_cstr(conn->id));
+        conn->status = SMSCCONN_ACTIVE;
+        conn->connect_time = time(NULL);
+        bb_smscconn_connected(conn);
+        
+        /* tell our login_manager to stop trying, ;-) */
+        cpa->logged_in = 1;
+    } else {
+        warning(0, "CPA[%s]: Login denied with status [%s] error_code [%s]", 
+                octstr_get_cstr(conn->id),
+                octstr_get_cstr(cpa_status), 
+                octstr_get_cstr(cpa_error_code)); 
+    }
+
+       retmsg = octstr_create("Ok.");
+
+    reply_headers = list_create();
+    http_header_add(reply_headers, "Content-Type", "text/plain");
+    debug("smsc.cpa", 0, "CPA[%s]: Sending reply",
+          octstr_get_cstr(conn->id));
+    http_send_reply(client, HTTP_OK, reply_headers, retmsg);
+
+    octstr_destroy(retmsg);
+    http_destroy_headers(reply_headers);
+
+    octstr_destroy(cpa_status);
+    octstr_destroy(cpa_error_code);
+}
+
+static void cpa_receiver(void *arg)
+{
+    SMSCConn *conn = arg;
+    CPA *cpa = conn->data;
+    HTTPClient *client;
+    Octstr *ip, *url, *body;
+    List *headers, *cgivars;
+
+    ip = url = body = NULL;
+    headers = cgivars = NULL;
+
+    /* Make sure we log into our own log-file if defined */
+    log_thread_to(conn->log_idx);
+ 
+    while (cpa->shutdown == 0) {
+
+        /* XXX if conn->is_stopped, do not receive new messages.. */
+       
+        client = http_accept_request(cpa->port, &ip, &url,
+                                     &headers, &body, &cgivars);
+        if (client == NULL)
+            break;
+
+        debug("smsc.cpa", 0, "CPA[%s]: Got request `%s'", 
+              octstr_get_cstr(conn->id), octstr_get_cstr(url));
+
+        if (connect_denied(cpa->allow_ip, ip)) {
+            info(0, "CPA[%s]: Connection `%s' tried from denied "
+                    "host %s, ignored", octstr_get_cstr(conn->id),
+                    octstr_get_cstr(url), octstr_get_cstr(ip));
+            http_close_client(client);
+        } else {
+            if (octstr_str_compare(url, "/txn_rsp")==0) {
+                cpa_process_response(conn, client, headers, body, cgivars);
+            } else if (octstr_str_compare(url, "/login_rsp")==0) {
+                cpa_process_login_response(conn, client, headers, body, cgivars);
+            } else if (octstr_str_compare(url, "/txn")==0) {
+                cpa_receive_sms(conn, client, headers, body, cgivars);
+            } else {
+                warning(0, "CPA[%s]: Invalid request", octstr_get_cstr(conn->id));
+            }
+        }
+
+        debug("smsc.cpa", 0, "CPA[%s]: Destroying client information",
+              octstr_get_cstr(conn->id));
+        octstr_destroy(url);
+        octstr_destroy(ip);
+        octstr_destroy(body);
+        http_destroy_headers(headers);
+        http_destroy_cgiargs(cgivars);
+    }
+    debug("smsc.cpa", 0, "CPA[%s]: httpsmsc_receiver dying",
+          octstr_get_cstr(conn->id));
+
+    cpa->shutdown = 1;
+    http_close_port(cpa->port);
+    
+    /* unblock http_receive_result() if there are no open sends */
+    if (cpa->open_sends == 0)
+        http_caller_signal_shutdown(cpa->http_ref);
+}
+
+/* this handles the login and session
+ * will attempt to connect if not connected
+ * will attempt to connect again after elapse_time
+ * will set the session_id for use in sending MT messsages
+ */
+static void login_manager(void *arg)
+{
+    SMSCConn *conn = arg;
+    CPA *cpa = conn->data;
+
+    /* we will sleep this amount of time one time */
+    int sleep_seconds = 10;
+
+    /* this will keep track of how many seconds have we passed, since the last login 
success */
+    int elapse_time_counter = 0;
+
+    debug("smsc.cpa", 0, "CPA[%s]: login manager started", octstr_get_cstr(conn->id));
+
+    /* TODO : tackle reconnect_delay config param */
+    while (cpa->shutdown == 0) {
+        if (! cpa->logged_in) {
+            /* we are not logged in, try to log in */
+            debug("smsc.cpa", 0, "CPA[%s]: not logged in, attempt to log in", 
octstr_get_cstr(conn->id));
+            send_login(cpa);
+
+            /* this should actually be set after we receive the login-rsp, but that's 
another thread,
+             * should be ok if we set it here */
+            elapse_time_counter = 0;
+        } else {
+            /* we are logged in, check if we need to reconnect */
+            if (elapse_time_counter >= (cpa->elapse_time * 60)) {
+                debug("smsc.cpa", 0, "CPA[%s]: session timed out", 
octstr_get_cstr(conn->id));
+                /* let the code above do the logging in */
+                cpa->logged_in = 0;
+
+                conn->status = SMSCCONN_RECONNECTING; 
+                continue;
+            }
+            elapse_time_counter += sleep_seconds;
+        }
+        gwthread_sleep(sleep_seconds);
+    }
+}
+
+/****
+ * Functions called by smscconn.c via SMSCConn function pointers
+ ****/
+
+static long queued_cb(SMSCConn *conn)
+{
+    CPA *cpa = conn->data;
+
+    return (cpa ? (conn->status != SMSCCONN_DEAD ? 
+            cpa->open_sends : 0) : 0);
+}
+
+static int cpa_send_msg(SMSCConn *conn, Msg *msg)
+{
+    CPA *cpa = conn->data;
+    Msg *sms = msg_duplicate(msg);
+    double delay = 0;
+
+    if (conn->throughput) {
+        delay = 1.0 / conn->throughput;
+    }
+
+    cpa->open_sends++;
+
+    cpa_send_sms(conn, sms);
+
+    /* obey throughput speed limit, if any */
+    if (conn->throughput)
+        gwthread_sleep(delay);
+
+    return 0;
+}
+
+/* TODO */
+static int shutdown_cb(SMSCConn *conn, int finish_sending)
+{
+
+}
+
+int smsc_cpa_create(SMSCConn *conn, CfgGroup *cfg)
+{
+    CPA *cpa = NULL;
+    long portno;   /* has to be long because of cfg_get_integer */
+    int ssl = 0;   /* indicate if SSL-enabled server should be used */
+    Octstr *smsc_id;
+
+    /* NOTE: httpsmsc incorrectly use the config param "port"
+     * in my view, "port" is to represent the smsc side
+     * "receive-port" is to represent our side
+     * so I change the param to "receive-port"
+     */
+    if (cfg_get_integer(&portno, cfg, octstr_imm("receive-port")) == -1) {
+        error(0, "CPA[%s]: 'receive-port' invalid in smsc 'cpa' record.",
+              octstr_get_cstr(conn->id));
+        return -1;
+    }
+
+    smsc_id = cfg_get(cfg, octstr_imm("smsc-id"));
+    if (smsc_id == NULL) 
+        smsc_id = octstr_duplicate(conn->name);
+
+    cpa = gw_malloc(sizeof(CPA));
+    cpa->http_ref = NULL;
+
+    cpa->allow_ip = cfg_get(cfg, octstr_imm("connect-allow-ip"));
+    cpa->send_url = cfg_get(cfg, octstr_imm("send-url"));
+    cpa->login_url = cfg_get(cfg, octstr_imm("login-url"));
+    cpa->username = cfg_get(cfg, octstr_imm("smsc-username"));
+    cpa->password = cfg_get(cfg, octstr_imm("smsc-password"));
+    cpa->cp_id = cfg_get(cfg, octstr_imm("cp-id"));
+    cpa->service_id = cfg_get(cfg, octstr_imm("service-id"));
+    cpa->short_code = cfg_get(cfg, octstr_imm("short-code"));
+    cpa->receive_host = cfg_get(cfg, octstr_imm("receive-host"));
+    cpa->prepaid_price_code = cfg_get(cfg, octstr_imm("prepaid-price-code"));
+    cpa->postpaid_price_code = cfg_get(cfg, octstr_imm("postpaid-price-code"));
+    cpa->charge_party = cfg_get(cfg, octstr_imm("charge-party"));
+    cpa->session_id = NULL;
+    cpa->elapse_time = 0;
+
+    if (cpa->send_url == NULL)
+        panic(0, "CPA[%s]: Sending not allowed. No 'send-url' specified.",
+              octstr_get_cstr(conn->id));
+
+    if (cpa->username == NULL) 
+        panic(0, "CPA[%s]: No smsc-username specified",
+              octstr_get_cstr(conn->id));
+
+    if (cpa->password == NULL) 
+        panic(0, "CPA[%s]: No smsc-password specified",
+              octstr_get_cstr(conn->id));
+
+    if (cpa->cp_id == NULL) 
+        panic(0, "CPA[%s]: No cp-id specified",
+              octstr_get_cstr(conn->id));
+
+    if (cpa->service_id == NULL) 
+        panic(0, "CPA[%s]: No service-id specified",
+              octstr_get_cstr(conn->id));
+
+    if (cpa->short_code == NULL) 
+        panic(0, "CPA[%s]: No short-code specified",
+              octstr_get_cstr(conn->id));
+
+    if (cpa->receive_host == NULL) 
+        panic(0, "CPA[%s]: No short-code specified",
+              octstr_get_cstr(conn->id));
+
+    if (cpa->prepaid_price_code == NULL) 
+        panic(0, "CPA[%s]: No prepaid-price-code specified",
+              octstr_get_cstr(conn->id));
+
+    if (cpa->postpaid_price_code == NULL) 
+        panic(0, "CPA[%s]: No postpaid-price-code specified",
+              octstr_get_cstr(conn->id));
+
+    if (cpa->charge_party == NULL) 
+        panic(0, "CPA[%s]: No charge-party specified",
+              octstr_get_cstr(conn->id));
+
+    /* url-encode the stuffs that we are sending over in HTTP header */
+    octstr_url_encode(cpa->username);
+    octstr_url_encode(cpa->password);
+    octstr_url_encode(cpa->cp_id);
+    octstr_url_encode(cpa->prepaid_price_code);
+    octstr_url_encode(cpa->postpaid_price_code);
+
+    cpa->open_sends = 0;
+    cpa->logged_in = 0;
+    cpa->http_ref = http_caller_create();
+    
+    conn->data = cpa;
+    conn->name = octstr_format("CPA");
+    conn->status = SMSCCONN_CONNECTING;
+    conn->connect_time = -1;
+
+    conn->shutdown = shutdown_cb;
+    conn->queued = queued_cb;
+    conn->send_msg = cpa_send_msg;
+
+    if (http_open_port_if(portno, ssl, conn->our_host)==-1)
+       goto error;
+
+    cpa->port = portno;
+    cpa->shutdown = 0;
+    
+    if ((cpa->login_thread = 
+        gwthread_create(login_manager, conn)) == -1)
+        goto error;
+
+    if ((cpa->receive_thread =
+           gwthread_create(cpa_receiver, conn)) == -1)
+       goto error;
+
+    if ((cpa->http_result_thread =
+        gwthread_create(cpa_http_receive_result, conn)) == -1)
+       goto error;
+
+    info(0, "CPA[%s]: Initiated and ready", octstr_get_cstr(conn->id));
+    
+    return 0;
+
+error:
+    error(0, "CPA[%s]: Failed to create http smsc connection",
+          octstr_get_cstr(conn->id));
+
+    conn->data = NULL;
+    cpa_destroy(cpa);
+    conn->why_killed = SMSCCONN_KILLED_CANNOT_CONNECT;
+    conn->status = SMSCCONN_DEAD;
+    return -1;
+}
+
+/* vim: ts=4 expandtab sw=4
+ */
diff -Naur kannel-snapshot/gw/smscconn.c kannel-snapshot-cpa/gw/smscconn.c
--- kannel-snapshot/gw/smscconn.c       2003-09-12 05:47:04.000000000 +0800
+++ kannel-snapshot-cpa/gw/smscconn.c   2003-11-18 09:41:57.000000000 +0800
@@ -181,6 +181,8 @@
         ret = smsc_cgw_create(conn,grp);
     else if (octstr_compare(smsc_type, octstr_imm("smasi")) == 0)
         ret = smsc_smasi_create(conn, grp);
+    else if (octstr_compare(smsc_type, octstr_imm("cpa")) == 0)
+        ret = smsc_cpa_create(conn, grp);
     else
         ret = smsc_wrapper_create(conn, grp);
 
diff -Naur kannel-snapshot/gw/smscconn_p.h kannel-snapshot-cpa/gw/smscconn_p.h
--- kannel-snapshot/gw/smscconn_p.h     2003-07-27 22:45:38.000000000 +0800
+++ kannel-snapshot-cpa/gw/smscconn_p.h 2003-11-18 09:42:22.000000000 +0800
@@ -215,6 +215,9 @@
 /* Responsible file: smsc/smsc_smasi.c */
 int smsc_smasi_create(SMSCConn *conn, CfgGroup *cfg);
 
+/* Responsible file: smsc/smsc_cpa.c */
+int smsc_cpa_create(SMSCConn *conn, CfgGroup *cfg);
+
 /* ADD NEW CREATE FUNCTIONS HERE
  *
  * int smsc_xxx_create(SMSCConn *conn, CfgGroup *cfg);
diff -Naur kannel-snapshot/gwlib/cfg.def kannel-snapshot-cpa/gwlib/cfg.def
--- kannel-snapshot/gwlib/cfg.def       2003-10-31 03:20:30.000000000 +0800
+++ kannel-snapshot-cpa/gwlib/cfg.def   2004-01-13 16:41:10.000000000 +0800
@@ -279,6 +279,15 @@
     OCTSTR(msg-id-type)
     OCTSTR(no-dlr)
     OCTSTR(connection-timeout)
+/* CPA stuffs */
+    OCTSTR(login-url)
+    OCTSTR(cp-id)
+    OCTSTR(service-id)
+    OCTSTR(short-code)
+    OCTSTR(receive-host)
+    OCTSTR(prepaid-price-code)
+    OCTSTR(postpaid-price-code)
+    OCTSTR(charge-party)
 )
 
 

Reply via email to