Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

smscconn.c

Go to the documentation of this file.
00001 /* ==================================================================== 
00002  * The Kannel Software License, Version 1.0 
00003  * 
00004  * Copyright (c) 2001-2008 Kannel Group  
00005  * Copyright (c) 1998-2001 WapIT Ltd.   
00006  * All rights reserved. 
00007  * 
00008  * Redistribution and use in source and binary forms, with or without 
00009  * modification, are permitted provided that the following conditions 
00010  * are met: 
00011  * 
00012  * 1. Redistributions of source code must retain the above copyright 
00013  *    notice, this list of conditions and the following disclaimer. 
00014  * 
00015  * 2. Redistributions in binary form must reproduce the above copyright 
00016  *    notice, this list of conditions and the following disclaimer in 
00017  *    the documentation and/or other materials provided with the 
00018  *    distribution. 
00019  * 
00020  * 3. The end-user documentation included with the redistribution, 
00021  *    if any, must include the following acknowledgment: 
00022  *       "This product includes software developed by the 
00023  *        Kannel Group (http://www.kannel.org/)." 
00024  *    Alternately, this acknowledgment may appear in the software itself, 
00025  *    if and wherever such third-party acknowledgments normally appear. 
00026  * 
00027  * 4. The names "Kannel" and "Kannel Group" must not be used to 
00028  *    endorse or promote products derived from this software without 
00029  *    prior written permission. For written permission, please  
00030  *    contact org@kannel.org. 
00031  * 
00032  * 5. Products derived from this software may not be called "Kannel", 
00033  *    nor may "Kannel" appear in their name, without prior written 
00034  *    permission of the Kannel Group. 
00035  * 
00036  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 
00037  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
00038  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
00039  * DISCLAIMED.  IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS 
00040  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,  
00041  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  
00042  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR  
00043  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
00044  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE  
00045  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,  
00046  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
00047  * ==================================================================== 
00048  * 
00049  * This software consists of voluntary contributions made by many 
00050  * individuals on behalf of the Kannel Group.  For more information on  
00051  * the Kannel Group, please see <http://www.kannel.org/>. 
00052  * 
00053  * Portions of this software are based upon software originally written at  
00054  * WapIT Ltd., Helsinki, Finland for the Kannel project.  
00055  */ 
00056 
00057 /*
00058  * SMSC Connection
00059  *
00060  * Interface for main bearerbox to SMS center connection modules
00061  *
00062  * Kalle Marjola 2000 for project Kannel
00063  */
00064 
00065 #include <signal.h>
00066 #include <time.h>
00067 
00068 #include "gwlib/gwlib.h"
00069 #include "gwlib/regex.h"
00070 #include "smscconn.h"
00071 #include "smscconn_p.h"
00072 #include "bb_smscconn_cb.h"
00073 #include "sms.h"
00074 
00075 extern Counter *split_msg_counter;
00076 
00077 /*
00078  * Some defaults
00079  */
00080 #define SMSCCONN_RECONNECT_DELAY     10.0
00081 
00082 
00083 /*
00084  * Add reroute information to the connection data. Where the priority
00085  * is in the order: reroute, reroute-smsc-id, reroute-receiver.
00086  */
00087 static void init_reroute(SMSCConn *conn, CfgGroup *grp)
00088 {
00089     Octstr *rule;
00090     long i;
00091 
00092     if (cfg_get_bool(&conn->reroute_dlr, grp, octstr_imm("reroute-dlr")) == -1)
00093         conn->reroute_dlr = 0;
00094     info(0, "DLR rerouting for smsc id <%s> %s.", octstr_get_cstr(conn->id), (conn->reroute_dlr?"enabled":"disabled"));
00095 
00096     if (cfg_get_bool(&conn->reroute, grp, octstr_imm("reroute")) != -1) {
00097         debug("smscconn",0,"Adding general internal routing for smsc id <%s>",
00098               octstr_get_cstr(conn->id));
00099         return;
00100     }
00101 
00102     if ((conn->reroute_to_smsc = cfg_get(grp, octstr_imm("reroute-smsc-id"))) != NULL) {
00103          /* reroute all messages to a specific smsc-id */
00104          debug("smscconn",0,"Adding internal routing: smsc id <%s> to smsc id <%s>",
00105                octstr_get_cstr(conn->id), octstr_get_cstr(conn->reroute_to_smsc));
00106         return;
00107     }
00108 
00109     if ((rule = cfg_get(grp, octstr_imm("reroute-receiver"))) != NULL) {
00110         List *routes;
00111 
00112         /* create hash disctionary for this smsc-id */
00113         conn->reroute_by_receiver = dict_create(100, (void(*)(void *)) octstr_destroy);
00114 
00115         routes = octstr_split(rule, octstr_imm(";"));
00116         for (i = 0; i < gwlist_len(routes); i++) {
00117             Octstr *item = gwlist_get(routes, i);
00118             Octstr *smsc, *receiver;
00119             List *receivers;
00120 
00121             /* first word is the smsc-id, all other are the receivers */
00122             receivers = octstr_split(item, octstr_imm(","));
00123             smsc = gwlist_extract_first(receivers);
00124             if (smsc)
00125                 octstr_strip_blanks(smsc);
00126 
00127             while((receiver = gwlist_extract_first(receivers))) {
00128                 octstr_strip_blanks(receiver);
00129                 debug("smscconn",0,"Adding internal routing for smsc id <%s>: "
00130                           "receiver <%s> to smsc id <%s>",
00131                           octstr_get_cstr(conn->id), octstr_get_cstr(receiver),
00132                           octstr_get_cstr(smsc));
00133                 if (!dict_put_once(conn->reroute_by_receiver, receiver, octstr_duplicate(smsc)))
00134                     panic(0, "Could not set internal routing for smsc id <%s>: "
00135                               "receiver <%s> to smsc id <%s>, because receiver has already routing entry!",
00136                               octstr_get_cstr(conn->id), octstr_get_cstr(receiver),
00137                               octstr_get_cstr(smsc));
00138                 octstr_destroy(receiver);
00139             }
00140             octstr_destroy(smsc);
00141             gwlist_destroy(receivers, octstr_destroy_item);
00142         }
00143         octstr_destroy(rule);
00144         gwlist_destroy(routes, octstr_destroy_item);
00145     }
00146 }
00147 
00148 
00149 SMSCConn *smscconn_create(CfgGroup *grp, int start_as_stopped)
00150 {
00151     SMSCConn *conn;
00152     Octstr *smsc_type;
00153     int ret;
00154     Octstr *allowed_smsc_id_regex;
00155     Octstr *denied_smsc_id_regex;
00156     Octstr *allowed_prefix_regex;
00157     Octstr *denied_prefix_regex;
00158     Octstr *preferred_prefix_regex;
00159     Octstr *tmp;
00160 
00161     if (grp == NULL)
00162     return NULL;
00163 
00164     conn = gw_malloc(sizeof(*conn));
00165     memset(conn, 0, sizeof(*conn));
00166 
00167     conn->why_killed = SMSCCONN_ALIVE;
00168     conn->status = SMSCCONN_CONNECTING;
00169     conn->connect_time = -1;
00170     conn->is_stopped = start_as_stopped;
00171 
00172     conn->received = counter_create();
00173     conn->sent = counter_create();
00174     conn->failed = counter_create();
00175     conn->flow_mutex = mutex_create();
00176 
00177 #define GET_OPTIONAL_VAL(x, n) x = cfg_get(grp, octstr_imm(n))
00178 #define SPLIT_OPTIONAL_VAL(x, n) \
00179         do { \
00180                 Octstr *tmp = cfg_get(grp, octstr_imm(n)); \
00181                 if (tmp) x = octstr_split(tmp, octstr_imm(";")); \
00182                 else x = NULL; \
00183                 octstr_destroy(tmp); \
00184         }while(0)
00185 
00186     GET_OPTIONAL_VAL(conn->id, "smsc-id");
00187     SPLIT_OPTIONAL_VAL(conn->allowed_smsc_id, "allowed-smsc-id");
00188     SPLIT_OPTIONAL_VAL(conn->denied_smsc_id, "denied-smsc-id");
00189     SPLIT_OPTIONAL_VAL(conn->preferred_smsc_id, "preferred-smsc-id");
00190     GET_OPTIONAL_VAL(conn->allowed_prefix, "allowed-prefix");
00191     GET_OPTIONAL_VAL(conn->denied_prefix, "denied-prefix");
00192     GET_OPTIONAL_VAL(conn->preferred_prefix, "preferred-prefix");
00193     GET_OPTIONAL_VAL(conn->unified_prefix, "unified-prefix");
00194     GET_OPTIONAL_VAL(conn->our_host, "our-host");
00195     GET_OPTIONAL_VAL(conn->log_file, "log-file");
00196     cfg_get_bool(&conn->alt_dcs, grp, octstr_imm("alt-dcs"));
00197 
00198     GET_OPTIONAL_VAL(allowed_smsc_id_regex, "allowed-smsc-id-regex");
00199     if (allowed_smsc_id_regex != NULL) 
00200         if ((conn->allowed_smsc_id_regex = gw_regex_comp(allowed_smsc_id_regex, REG_EXTENDED)) == NULL)
00201             panic(0, "Could not compile pattern '%s'", octstr_get_cstr(allowed_smsc_id_regex));
00202     GET_OPTIONAL_VAL(denied_smsc_id_regex, "denied-smsc-id-regex");
00203     if (denied_smsc_id_regex != NULL) 
00204         if ((conn->denied_smsc_id_regex = gw_regex_comp(denied_smsc_id_regex, REG_EXTENDED)) == NULL)
00205             panic(0, "Could not compile pattern '%s'", octstr_get_cstr(denied_smsc_id_regex));
00206     GET_OPTIONAL_VAL(allowed_prefix_regex, "allowed-prefix-regex");
00207     if (allowed_prefix_regex != NULL) 
00208         if ((conn->allowed_prefix_regex = gw_regex_comp(allowed_prefix_regex, REG_EXTENDED)) == NULL)
00209             panic(0, "Could not compile pattern '%s'", octstr_get_cstr(allowed_prefix_regex));
00210     GET_OPTIONAL_VAL(denied_prefix_regex, "denied-prefix-regex");
00211     if (denied_prefix_regex != NULL) 
00212         if ((conn->denied_prefix_regex = gw_regex_comp(denied_prefix_regex, REG_EXTENDED)) == NULL)
00213             panic(0, "Could not compile pattern '%s'", octstr_get_cstr(denied_prefix_regex));
00214     GET_OPTIONAL_VAL(preferred_prefix_regex, "preferred-prefix-regex");
00215     if (preferred_prefix_regex != NULL) 
00216         if ((conn->preferred_prefix_regex = gw_regex_comp(preferred_prefix_regex, REG_EXTENDED)) == NULL)
00217             panic(0, "Could not compile pattern '%s'", octstr_get_cstr(preferred_prefix_regex));
00218 
00219     if ((tmp = cfg_get(grp, octstr_imm("throughput"))) != NULL) {
00220         if (octstr_parse_double(&conn->throughput, tmp, 0) == -1)
00221             conn->throughput = 0;
00222         octstr_destroy(tmp);
00223         info(0, "Set throughput to %.3f for smsc id <%s>", conn->throughput, octstr_get_cstr(conn->id));
00224     }
00225 
00226     /* configure the internal rerouting rules for this smsc id */
00227     init_reroute(conn, grp);
00228 
00229     if (cfg_get_integer(&conn->log_level, grp, octstr_imm("log-level")) == -1)
00230         conn->log_level = 0;
00231 
00232     if (cfg_get_integer(&conn->max_sms_octets, grp, octstr_imm("max-sms-octets")) == -1)
00233         conn->max_sms_octets = MAX_SMS_OCTETS;
00234 
00235     /* open a smsc-id specific log-file in exlusive mode */
00236     if (conn->log_file)
00237         conn->log_idx = log_open(octstr_get_cstr(conn->log_file), 
00238                                  conn->log_level, GW_EXCL); 
00239 #undef GET_OPTIONAL_VAL
00240 #undef SPLIT_OPTIONAL_VAL
00241 
00242     if (conn->allowed_smsc_id && conn->denied_smsc_id)
00243     warning(0, "Both 'allowed-smsc-id' and 'denied-smsc-id' set, deny-list "
00244         "automatically ignored");
00245     if (conn->allowed_smsc_id_regex && conn->denied_smsc_id_regex)
00246         warning(0, "Both 'allowed-smsc-id_regex' and 'denied-smsc-id_regex' set, deny-regex "
00247                 "automatically ignored");
00248 
00249     if (cfg_get_integer(&conn->reconnect_delay, grp,
00250                         octstr_imm("reconnect-delay")) == -1)
00251         conn->reconnect_delay = SMSCCONN_RECONNECT_DELAY;
00252 
00253     smsc_type = cfg_get(grp, octstr_imm("smsc"));
00254     if (smsc_type == NULL) {
00255         error(0, "Required field 'smsc' missing for smsc group.");
00256         smscconn_destroy(conn);
00257         octstr_destroy(smsc_type);
00258         return NULL;
00259     }
00260 
00261     if (octstr_compare(smsc_type, octstr_imm("fake")) == 0)
00262         ret = smsc_fake_create(conn, grp);
00263     else if (octstr_compare(smsc_type, octstr_imm("cimd2")) == 0)
00264     ret = smsc_cimd2_create(conn, grp);
00265     else if (octstr_compare(smsc_type, octstr_imm("emi")) == 0)
00266     ret = smsc_emi2_create(conn, grp);
00267     else if (octstr_compare(smsc_type, octstr_imm("http")) == 0)
00268         ret = smsc_http_create(conn, grp);
00269     else if (octstr_compare(smsc_type, octstr_imm("smpp")) == 0)
00270     ret = smsc_smpp_create(conn, grp);
00271     else if (octstr_compare(smsc_type, octstr_imm("at")) == 0)
00272     ret = smsc_at2_create(conn,grp);
00273     else if (octstr_compare(smsc_type, octstr_imm("cgw")) == 0)
00274         ret = smsc_cgw_create(conn,grp);
00275     else if (octstr_compare(smsc_type, octstr_imm("smasi")) == 0)
00276         ret = smsc_smasi_create(conn, grp);
00277     else if (octstr_compare(smsc_type, octstr_imm("oisd")) == 0)
00278         ret = smsc_oisd_create(conn, grp);
00279     else
00280         ret = smsc_wrapper_create(conn, grp);
00281 
00282     octstr_destroy(smsc_type);
00283     if (ret == -1) {
00284         smscconn_destroy(conn);
00285         return NULL;
00286     }
00287     gw_assert(conn->send_msg != NULL);
00288 
00289     bb_smscconn_ready(conn);
00290 
00291     return conn;
00292 }
00293 
00294 
00295 void smscconn_shutdown(SMSCConn *conn, int finish_sending)
00296 {
00297     gw_assert(conn != NULL);
00298     mutex_lock(conn->flow_mutex);
00299     if (conn->status == SMSCCONN_DEAD) {
00300     mutex_unlock(conn->flow_mutex);
00301     return;
00302     }
00303 
00304     /* Call SMSC specific destroyer */
00305     if (conn->shutdown) {
00306         /* 
00307          * we must unlock here, because module manipulate their state
00308          * and will try to lock this mutex.Otherwise we have deadlock!
00309          */
00310         mutex_unlock(conn->flow_mutex);
00311     conn->shutdown(conn, finish_sending);
00312     }
00313     else {
00314     conn->why_killed = SMSCCONN_KILLED_SHUTDOWN;
00315         mutex_unlock(conn->flow_mutex);
00316     }
00317 
00318     return;
00319 }
00320 
00321 
00322 int smscconn_destroy(SMSCConn *conn)
00323 {
00324     if (conn == NULL)
00325     return 0;
00326     if (conn->status != SMSCCONN_DEAD)
00327     return -1;
00328     mutex_lock(conn->flow_mutex);
00329 
00330     counter_destroy(conn->received);
00331     counter_destroy(conn->sent);
00332     counter_destroy(conn->failed);
00333 
00334     octstr_destroy(conn->name);
00335     octstr_destroy(conn->id);
00336     gwlist_destroy(conn->allowed_smsc_id, octstr_destroy_item);
00337     gwlist_destroy(conn->denied_smsc_id, octstr_destroy_item);
00338     gwlist_destroy(conn->preferred_smsc_id, octstr_destroy_item);
00339     octstr_destroy(conn->denied_prefix);
00340     octstr_destroy(conn->allowed_prefix);
00341     octstr_destroy(conn->preferred_prefix);
00342     octstr_destroy(conn->unified_prefix);
00343     octstr_destroy(conn->our_host);
00344     octstr_destroy(conn->log_file);
00345 
00346     if (conn->denied_smsc_id_regex != NULL) gw_regex_destroy(conn->denied_smsc_id_regex);
00347     if (conn->allowed_smsc_id_regex != NULL) gw_regex_destroy(conn->allowed_smsc_id_regex);
00348     if (conn->preferred_prefix_regex != NULL) gw_regex_destroy(conn->preferred_prefix_regex);
00349     if (conn->denied_prefix_regex != NULL) gw_regex_destroy(conn->denied_prefix_regex);
00350     if (conn->allowed_prefix_regex != NULL) gw_regex_destroy(conn->allowed_prefix_regex);
00351 
00352     octstr_destroy(conn->reroute_to_smsc);
00353     dict_destroy(conn->reroute_by_receiver);
00354 
00355     mutex_unlock(conn->flow_mutex);
00356     mutex_destroy(conn->flow_mutex);
00357 
00358     gw_free(conn);
00359     return 0;
00360 }
00361 
00362 
00363 int smscconn_stop(SMSCConn *conn)
00364 {
00365     gw_assert(conn != NULL);
00366     mutex_lock(conn->flow_mutex);
00367     if (conn->status == SMSCCONN_DEAD || conn->is_stopped != 0
00368     || conn->why_killed != SMSCCONN_ALIVE)
00369     {
00370     mutex_unlock(conn->flow_mutex);
00371     return -1;
00372     }
00373     conn->is_stopped = 1;
00374     mutex_unlock(conn->flow_mutex);
00375 
00376     if (conn->stop_conn)
00377     conn->stop_conn(conn);
00378 
00379     return 0;
00380 }
00381 
00382 
00383 void smscconn_start(SMSCConn *conn)
00384 {
00385     gw_assert(conn != NULL);
00386     mutex_lock(conn->flow_mutex);
00387     if (conn->status == SMSCCONN_DEAD || conn->is_stopped == 0) {
00388     mutex_unlock(conn->flow_mutex);
00389     return;
00390     }
00391     conn->is_stopped = 0;
00392     mutex_unlock(conn->flow_mutex);
00393     
00394      if (conn->start_conn)
00395     conn->start_conn(conn);
00396 }
00397 
00398 
00399 const Octstr *smscconn_name(SMSCConn *conn)
00400 {
00401     gw_assert(conn != NULL);
00402     return conn->name;
00403 }
00404 
00405 
00406 const Octstr *smscconn_id(SMSCConn *conn)
00407 {
00408     gw_assert(conn != NULL);
00409     return conn->id;
00410 }
00411 
00412 
00413 int smscconn_usable(SMSCConn *conn, Msg *msg)
00414 {
00415     gw_assert(conn != NULL);
00416     gw_assert(msg != NULL && msg_type(msg) == sms);
00417 
00418     if (conn->status == SMSCCONN_DEAD || conn->why_killed != SMSCCONN_ALIVE)
00419     return -1;
00420 
00421     /* if allowed-smsc-id set, then only allow this SMSC if message
00422      * smsc-id matches any of its allowed SMSCes
00423      */
00424     if (conn->allowed_smsc_id && (msg->sms.smsc_id == NULL ||
00425          gwlist_search(conn->allowed_smsc_id, msg->sms.smsc_id, octstr_item_match) == NULL)) {
00426         return -1;
00427     }
00428     /* ..if no allowed-smsc-id set but denied-smsc-id and message smsc-id
00429      * is set, deny message if smsc-ids match */
00430     else if (conn->denied_smsc_id && msg->sms.smsc_id != NULL &&
00431                  gwlist_search(conn->denied_smsc_id, msg->sms.smsc_id, octstr_item_match) != NULL) {
00432         return -1;
00433     }
00434 
00435     if (conn->allowed_smsc_id_regex) {
00436         if (msg->sms.smsc_id == NULL)
00437             return -1;
00438         
00439         if (gw_regex_match_pre(conn->allowed_smsc_id_regex, msg->sms.smsc_id) == 0) 
00440             return -1;
00441     }
00442     else if (conn->denied_smsc_id_regex && msg->sms.smsc_id != NULL) {
00443         if (gw_regex_match_pre(conn->denied_smsc_id_regex, msg->sms.smsc_id) == 1) 
00444             return -1;
00445     }
00446 
00447     /* Have allowed */
00448     if (conn->allowed_prefix && ! conn->denied_prefix && 
00449        (does_prefix_match(conn->allowed_prefix, msg->sms.receiver) != 1))
00450     return -1;
00451     
00452     if (conn->allowed_prefix_regex && ! conn->denied_prefix_regex) {
00453         if (gw_regex_match_pre(conn->allowed_prefix_regex, msg->sms.receiver) == 0)
00454             return -1;
00455     }
00456 
00457     /* Have denied */
00458     if (conn->denied_prefix && ! conn->allowed_prefix &&
00459        (does_prefix_match(conn->denied_prefix, msg->sms.receiver) == 1))
00460     return -1;
00461 
00462     if (conn->denied_prefix_regex && ! conn->allowed_prefix_regex) {
00463         if (gw_regex_match_pre(conn->denied_prefix_regex, msg->sms.receiver) == 1)
00464             return -1;
00465     }
00466 
00467     /* Have allowed and denied */
00468     if (conn->denied_prefix && conn->allowed_prefix &&
00469        (does_prefix_match(conn->allowed_prefix, msg->sms.receiver) != 1) &&
00470        (does_prefix_match(conn->denied_prefix, msg->sms.receiver) == 1) )
00471     return -1;
00472 
00473     if (conn->allowed_prefix_regex && conn->denied_prefix_regex) {
00474         if (gw_regex_match_pre(conn->allowed_prefix_regex, msg->sms.receiver) == 0 &&
00475             gw_regex_match_pre(conn->denied_prefix_regex, msg->sms.receiver) == 1)
00476             return -1;
00477     }
00478     
00479     /* then see if it is preferred one */
00480     if (conn->preferred_smsc_id && msg->sms.smsc_id != NULL &&
00481          gwlist_search(conn->preferred_smsc_id, msg->sms.smsc_id, octstr_item_match) != NULL) {
00482         return 1;
00483     }
00484 
00485     if (conn->preferred_prefix)
00486     if (does_prefix_match(conn->preferred_prefix, msg->sms.receiver) == 1)
00487         return 1;
00488 
00489     if (conn->preferred_prefix_regex &&
00490         gw_regex_match_pre(conn->preferred_prefix_regex, msg->sms.receiver) == 1) {
00491         return 1;
00492     }
00493         
00494     return 0;
00495 }
00496 
00497 
00498 int smscconn_send(SMSCConn *conn, Msg *msg)
00499 {
00500     int ret = -1;
00501     List *parts = NULL;
00502     
00503     gw_assert(conn != NULL);
00504     mutex_lock(conn->flow_mutex);
00505     if (conn->status == SMSCCONN_DEAD || conn->why_killed != SMSCCONN_ALIVE) {
00506         mutex_unlock(conn->flow_mutex);
00507         return -1;
00508     }
00509 
00510     /* if this a retry of splitted message, don't unify prefix and don't try to split */
00511     if (msg->sms.split_parts == NULL) {    
00512         /* normalize the destination number for this smsc */
00513         char *uf = conn->unified_prefix ? octstr_get_cstr(conn->unified_prefix) : NULL;
00514         normalize_number(uf, &(msg->sms.receiver));
00515 
00516         /* split msg */
00517         parts = sms_split(msg, NULL, NULL, NULL, NULL, 1, 
00518             counter_increase(split_msg_counter) & 0xff, 0xff, conn->max_sms_octets);
00519         if (gwlist_len(parts) == 1) {
00520             /* don't create split_parts of sms fit into one */
00521             gwlist_destroy(parts, msg_destroy_item);
00522             parts = NULL;
00523         }
00524     }
00525     
00526     if (parts == NULL)
00527         ret = conn->send_msg(conn, msg);
00528     else {
00529         long i, parts_len = gwlist_len(parts);
00530         struct split_parts *split = gw_malloc(sizeof(*split));
00531          /* must duplicate, because smsc2_route will destroy this msg */
00532         split->orig = msg_duplicate(msg);
00533         split->parts_left = counter_create();
00534         split->status = SMSCCONN_SUCCESS;
00535         counter_set(split->parts_left, parts_len);
00536         debug("bb.sms.splits", 0, "new split_parts created %p", split);
00537         for (i = 0; i < parts_len; i++) {
00538             msg = gwlist_get(parts, i);
00539             msg->sms.split_parts = split;
00540             ret = conn->send_msg(conn, msg);
00541             if (ret < 0) {
00542                 if (i == 0) {
00543                     counter_destroy(split->parts_left);
00544                     gwlist_destroy(parts, msg_destroy_item);
00545                     gw_free(split);
00546                     mutex_unlock(conn->flow_mutex);
00547                     return ret;
00548                 }
00549                 /*
00550                  * Some parts were sent. So handle this within
00551                  * bb_smscconn_XXX().
00552                  */
00553                 split->status = SMSCCONN_FAILED_REJECTED;
00554                 counter_increase_with(split->parts_left, -(parts_len - i));
00555                 warning(0, "Could not send all parts of a split message");
00556                 break;
00557             }
00558         }
00559         gwlist_destroy(parts, msg_destroy_item);
00560     }
00561     mutex_unlock(conn->flow_mutex);
00562     return ret;
00563 }
00564 
00565 
00566 int smscconn_status(SMSCConn *conn)
00567 {
00568     gw_assert(conn != NULL);
00569 
00570     return conn->status;
00571 }
00572 
00573 
00574 int smscconn_info(SMSCConn *conn, StatusInfo *infotable)
00575 {
00576     if (conn == NULL || infotable == NULL)
00577     return -1;
00578 
00579     mutex_lock(conn->flow_mutex);
00580 
00581     infotable->status = conn->status;
00582     infotable->killed = conn->why_killed;
00583     infotable->is_stopped = conn->is_stopped;
00584     infotable->online = time(NULL) - conn->connect_time;
00585     
00586     infotable->sent = counter_value(conn->sent);
00587     infotable->received = counter_value(conn->received);
00588     infotable->failed = counter_value(conn->failed);
00589 
00590     if (conn->queued)
00591     infotable->queued = conn->queued(conn);
00592     else
00593     infotable->queued = -1;
00594 
00595     infotable->load = conn->load;
00596     
00597     mutex_unlock(conn->flow_mutex);
00598 
00599     return 0;
00600 }
00601 
00602 
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.