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

smsc_cgw.c File Reference

#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"

Include dependency graph for smsc_cgw.c:

Include dependency graph

Go to the source code of this file.

Data Structures

struct  cgwop
struct  privdata

Defines

#define CGW_DEFPORT   21772
#define CGW_EOL   0x0A
#define CGW_TRN_MAX   500
#define CGWOP_MAXARGS   10
#define CGW_OP_NOP   0
#define CGW_OP_MSG   1
#define CGW_OP_OK   2
#define CGW_OP_ERR   3
#define CGW_OP_DELIVERY   4
#define CGW_OP_HELLO   5
#define CGW_OP_STATUS   6

Typedefs

typedef privdata PrivData

Functions

int cgw_add_msg_cb (SMSCConn *conn, Msg *sms)
int cgw_shutdown_cb (SMSCConn *conn, int finish_sending)
void cgw_start_cb (SMSCConn *conn)
long cgw_queued_cb (SMSCConn *conn)
void cgw_sender (void *arg)
Connectioncgw_open_send_connection (SMSCConn *conn)
int cgw_send_loop (SMSCConn *conn, Connection *server)
void cgw_check_acks (PrivData *privdata)
int cgw_wait_command (PrivData *privdata, SMSCConn *conn, Connection *server, int timeout)
int cgw_open_listening_socket (SMSCConn *conn, PrivData *privdata)
void cgw_listener (void *arg)
void cgw_receiver (SMSCConn *conn, Connection *server)
int cgw_handle_op (SMSCConn *conn, Connection *server, struct cgwop *cgwop)
cgwopcgw_read_op (PrivData *privdata, SMSCConn *conn, Connection *server, time_t timeout)
void cgwop_add (struct cgwop *cgwop, Octstr *name, Octstr *value)
cgwopcgwop_create (int op, int trn)
void cgwop_destroy (struct cgwop *cgwop)
Octstrcgwop_get (struct cgwop *cgwop, Octstr *name)
Octstrcgwop_tostr (struct cgwop *cgwop)
int cgwop_send (Connection *conn, struct cgwop *cgwop)
Octstrcgw_encode_msg (Octstr *str)
Octstrcgw_decode_msg (Octstr *str)
cgwopmsg_to_cgwop (PrivData *privdata, Msg *msg, int trn)
int smsc_cgw_create (SMSCConn *conn, CfgGroup *cfg)

Variables

char * cgw_ops [6] = {"nop", "msg", "ok", "err", "delivery", "hello"}


Define Documentation

#define CGW_DEFPORT   21772
 

Definition at line 123 of file smsc_cgw.c.

Referenced by smsc_cgw_create().

#define CGW_EOL   0x0A
 

Definition at line 124 of file smsc_cgw.c.

Referenced by cgw_encode_msg(), and cgwop_tostr().

#define CGW_OP_DELIVERY   4
 

Definition at line 135 of file smsc_cgw.c.

Referenced by cgw_handle_op().

#define CGW_OP_ERR   3
 

Definition at line 134 of file smsc_cgw.c.

Referenced by cgw_handle_op().

#define CGW_OP_HELLO   5
 

Definition at line 136 of file smsc_cgw.c.

Referenced by cgw_handle_op().

#define CGW_OP_MSG   1
 

Definition at line 132 of file smsc_cgw.c.

Referenced by cgw_handle_op(), and msg_to_cgwop().

#define CGW_OP_NOP   0
 

Definition at line 131 of file smsc_cgw.c.

#define CGW_OP_OK   2
 

Definition at line 133 of file smsc_cgw.c.

Referenced by cgw_handle_op().

#define CGW_OP_STATUS   6
 

Definition at line 137 of file smsc_cgw.c.

Referenced by cgw_handle_op().

#define CGW_TRN_MAX   500
 

Definition at line 125 of file smsc_cgw.c.

#define CGWOP_MAXARGS   10
 

Definition at line 127 of file smsc_cgw.c.

Referenced by cgwop_create().


Typedef Documentation

typedef struct privdata PrivData
 

Referenced by add_msg_cb(), cgw_add_msg_cb(), cgw_check_acks(), cgw_handle_op(), cgw_listener(), cgw_open_listening_socket(), cgw_open_send_connection(), cgw_queued_cb(), cgw_read_op(), cgw_receiver(), cgw_send_loop(), cgw_sender(), cgw_shutdown_cb(), cgw_start_cb(), cgw_wait_command(), cimd2_add_msg_cb(), cimd2_close_socket(), cimd2_destroy(), cimd2_get_packet(), cimd2_handle_request(), cimd2_login(), cimd2_queued_cb(), cimd2_receive_msg(), cimd2_request(), cimd2_send_response(), cimd2_shutdown_cb(), cimd2_start_cb(), cimd2_stop_cb(), cimd2_submit_msg(), clear_sent(), emi2_handle_smscreq(), emi2_idleprocessing(), emi2_idletimeout_handling(), emi2_listener(), emi2_open_listening_socket(), emi2_receiver(), emi2_send_loop(), emi2_sender(), fake_listener(), fake_open_connection(), handle_operation(), io_thread(), main_connection_loop(), make_emi31(), make_emi60(), msg_to_cgwop(), msg_to_emimsg(), oisd_add_msg_cb(), oisd_close_socket(), oisd_destroy(), oisd_get_packet(), oisd_handle_request(), oisd_login(), oisd_queued_cb(), oisd_receive_msg(), oisd_request(), oisd_send_delivery_request(), oisd_send_response(), oisd_shutdown_cb(), oisd_start_cb(), oisd_stop_cb(), oisd_submit_msg(), open_send_connection(), packet_encode_message(), packet_set_send_sequence(), queued_cb(), shutdown_cb(), sms_receive(), smsc_cgw_create(), smsc_cimd2_create(), smsc_emi2_create(), smsc_fake_create(), smsc_oisd_create(), smsc_soap_create(), soap_add_msg_cb(), soap_client_init_query(), soap_convert_token(), soap_format_xml(), soap_listener(), soap_msgdata_attribute(), soap_msgdata_deps(), soap_o2o_msgdata_attribute(), soap_parse_dlr(), soap_parse_mo(), soap_parse_response(), soap_process_deps(), soap_queued_cb(), soap_read_response(), soap_release_dependences(), soap_select_function(), soap_send(), soap_send_loop(), soap_server(), soap_server_start(), soap_server_stop(), soap_shutdown_cb(), soap_start_cb(), soap_stop_cb(), start_cb(), and wait_for_ack().


Function Documentation

int cgw_add_msg_cb SMSCConn conn,
Msg sms
[static]
 

Definition at line 549 of file smsc_cgw.c.

References smscconn::data, gwlist_produce(), gwthread_wakeup(), msg_duplicate(), privdata::outgoing_queue, PrivData, privdata::sender_thread, sms, and SMSCConn.

00550 {
00551     PrivData *privdata = conn->data;
00552     Msg *copy;
00553 
00554     copy = msg_duplicate(sms);
00555     gwlist_produce(privdata->outgoing_queue, copy);
00556     gwthread_wakeup(privdata->sender_thread);
00557 
00558     return 0;
00559 }

Here is the call graph for this function:

void cgw_check_acks PrivData privdata  ) 
 

Definition at line 787 of file smsc_cgw.c.

References privdata::check_time, gwlist_produce(), privdata::outgoing_queue, PrivData, privdata::sendmsg, privdata::sendtime, privdata::unacked, privdata::waitack, and warning().

Referenced by cgw_sender().

00788 {
00789     time_t  current_time;
00790     int i;
00791 
00792     current_time = time(NULL);
00793     if (privdata->unacked && (current_time > privdata->check_time + 30)) {
00794         privdata->check_time = current_time;
00795         for (i = 0; i < CGW_TRN_MAX; i++)
00796             if (privdata->sendtime[i] && privdata->sendtime[i] < (current_time - privdata->waitack)) {
00797                 privdata->sendtime[i] = 0;
00798                 privdata->unacked--;
00799                 warning(0, "smsc_cgw: received neither OK nor ERR for message %d "
00800                         "in %d seconds, resending message", i, privdata->waitack);
00801                 gwlist_produce(privdata->outgoing_queue, privdata->sendmsg[i]);
00802             }
00803     }
00804 }

Here is the call graph for this function:

Octstr* cgw_decode_msg Octstr str  )  [static]
 

Definition at line 354 of file smsc_cgw.c.

References octstr_delete(), octstr_imm(), octstr_insert(), and octstr_search().

Referenced by cgw_handle_op().

00355 {
00356     int i;
00357 
00358     /* make \n -> linefeed */
00359     while ((i = octstr_search(str, octstr_imm("\\n"), 0)) != -1) {
00360         octstr_delete(str, i, 2);     /* delete "\n" str */
00361         octstr_insert(str, octstr_imm("\n"), i);
00362     }
00363     /* make \r -> carriage return */
00364     while ((i = octstr_search(str, octstr_imm("\\r"), 0)) != -1) {
00365         octstr_delete(str, i, 2);     /* delete EOL char */
00366         octstr_insert(str, octstr_imm("\r"), i);
00367     }
00368     /* remove double backslashes */
00369     while ((i = octstr_search(str, octstr_imm("\\\\"), 0)) != -1) {
00370         octstr_delete(str, i, 1);
00371     }
00372 
00373     return str;
00374 }

Here is the call graph for this function:

Octstr* cgw_encode_msg Octstr str  )  [static]
 

Definition at line 312 of file smsc_cgw.c.

References CGW_EOL, octstr_delete(), octstr_imm(), octstr_insert(), octstr_insert_data(), octstr_len(), and octstr_search_char().

Referenced by msg_to_cgwop().

00313 {
00314     int i;
00315     char esc = 27;
00316     char e = 'e';
00317 
00318     /* Euro char (0x80) -> ESC + e. We do this conversion as long as the message 
00319        length is under 160 chars (the checking could probably be done better) */
00320 
00321     while ((i = octstr_search_char(str, 0x80, 0)) != -1) {    
00322         octstr_delete(str, i, 1);     /* delete Euro char */
00323     if (octstr_len(str) < 160) {
00324         octstr_insert_data(str, i, &esc, 1);  /* replace with ESC + e */
00325         octstr_insert_data(str, i+1, &e, 1);  
00326     } else {
00327         octstr_insert_data(str, i, &e, 1);  /* no room for ESC + e, just replace with an e */
00328         }
00329     }
00330 
00331 
00332     /* Escape backslash characters */
00333     while ((i = octstr_search_char(str, '\\', 0)) != -1) {
00334         octstr_insert(str, octstr_imm("\\"), i);
00335     }
00336     /* Remove Line Feed characters */
00337     while ((i = octstr_search_char(str, CGW_EOL, 0)) != -1) {
00338         octstr_delete(str, i, 1);     /* delete EOL char */
00339         octstr_insert(str, octstr_imm("\\n"), i);
00340     }
00341     /* Remove Carriage return characters */
00342     while ((i = octstr_search_char(str, 13, 0)) != -1) {
00343         octstr_delete(str, i, 1);     /* delete EOL char */
00344         octstr_insert(str, octstr_imm("\\r"), i);
00345     }
00346 
00347     return str;
00348 }

Here is the call graph for this function:

int cgw_handle_op SMSCConn conn,
Connection server,
struct cgwop cgwop
[static]
 

Definition at line 1067 of file smsc_cgw.c.

References bb_smscconn_receive(), bb_smscconn_send_failed(), bb_smscconn_sent(), cgw_decode_msg(), CGW_OP_DELIVERY, CGW_OP_ERR, CGW_OP_HELLO, CGW_OP_MSG, CGW_OP_OK, CGW_OP_STATUS, cgwop_add(), cgwop_create(), cgwop_destroy(), cgwop_get(), cgwop_send(), smscconn::data, privdata::dlr, dlr_add(), DLR_BUFFERED, DLR_FAIL, dlr_find(), DLR_IS_ENABLED_DEVICE, DLR_SUCCESS, smscconn::id, info(), msg_create, octstr_append(), octstr_append_char(), octstr_append_decimal(), octstr_create, octstr_destroy(), octstr_duplicate, octstr_get_cstr, octstr_imm(), octstr_parse_long(), cgwop::op, PrivData, privdata::sendmsg, privdata::sendtime, sms, SMSCConn, SMSCCONN_FAILED_REJECTED, and privdata::unacked.

Referenced by cgw_receiver(), and cgw_wait_command().

01068 {
01069     PrivData *privdata = conn->data;
01070     Msg *msg = NULL;
01071     Octstr *from, *app, *sid, *to, *msgtype, *msgdata; /* for messages */
01072     Octstr *msid, *status, *txt;                   /* delivery reports */
01073     Octstr *clid;                              /* for acks */
01074     struct cgwop *reply = NULL;
01075     long trn, stat;                          /* transaction number for ack */
01076     Msg *dlrmsg = NULL, *origmsg = NULL;
01077     Octstr *ts;
01078 
01079     if (cgwop == NULL) return 0;
01080 
01081     from = cgwop_get(cgwop, octstr_imm("from"));
01082     app = cgwop_get(cgwop, octstr_imm("app"));
01083     sid = cgwop_get(cgwop, octstr_imm("session-id"));
01084     to = cgwop_get(cgwop, octstr_imm("to"));
01085     msgtype = cgwop_get(cgwop, octstr_imm("type"));
01086     msgdata = cgwop_get(cgwop, octstr_imm("msg"));
01087     txt = cgwop_get(cgwop, octstr_imm("txt"));
01088 
01089     msid = cgwop_get(cgwop, octstr_imm("msid"));
01090     status = cgwop_get(cgwop, octstr_imm("status"));
01091     clid = cgwop_get(cgwop, octstr_imm("client-id"));
01092 
01093     if (clid != NULL)
01094     {
01095         octstr_parse_long(&trn, clid, 0, 10);
01096         if ((trn < 0) || (trn >= CGW_TRN_MAX)) { /* invalid transaction number */
01097         info(0, "cgw: Invalid transaction number: %d", (int) trn);
01098             trn = -1;            
01099         return 0;
01100         }
01101     }
01102 
01103     switch (cgwop->op)
01104     {
01105     case CGW_OP_MSG:
01106         msg = msg_create(sms);
01107         time(&msg->sms.time);
01108         msg->sms.msgdata = cgw_decode_msg(octstr_duplicate(msgdata));
01109         msg->sms.sender = octstr_duplicate(from);
01110         msg->sms.receiver = octstr_duplicate(to);
01111         msg->sms.smsc_id = octstr_duplicate(conn->id);
01112         bb_smscconn_receive(conn, msg);
01113 
01114         reply = cgwop_create(CGW_OP_OK, -1);
01115         cgwop_add(reply, octstr_imm("session-id"), sid);
01116         cgwop_send(server, reply);     /* send reply */
01117 
01118         cgwop_destroy(reply);
01119 
01120         break;
01121 
01122     case CGW_OP_DELIVERY:
01123         if (privdata->dlr[trn]) {
01124 
01125             octstr_parse_long(&stat, status, 0, 10);
01126             origmsg = privdata->sendmsg[trn];
01127 
01128             if (origmsg == NULL) break;
01129 
01130             ts = octstr_create("");
01131             octstr_append(ts, conn->id);
01132             octstr_append_char(ts, '-');
01133             octstr_append_decimal(ts, trn);
01134 
01135             switch (stat) {
01136             case 0:     /* delivered */
01137                 dlrmsg = dlr_find(conn->id,
01138                                             ts,     /* timestamp */
01139                                             msid,   /* destination */
01140                                   DLR_SUCCESS);
01141                 break;
01142             case 1:     /* buffered */
01143                 dlrmsg = dlr_find(conn->id,
01144                                             ts,     /* timestamp */
01145                                             msid,   /* destination */
01146                                   DLR_BUFFERED);
01147                 break;
01148             case 2:     /* not delivered */
01149                 dlrmsg = dlr_find(conn->id,
01150                                             ts,     /* timestamp */
01151                                             msid,   /* destination */
01152                                   DLR_FAIL);
01153                 break;
01154             }
01155 
01156             octstr_destroy(ts);
01157             if (dlrmsg != NULL) {
01158                 dlrmsg->sms.msgdata = octstr_duplicate(txt);
01159                 bb_smscconn_receive(conn, dlrmsg);
01160             }
01161         }
01162 
01163         break;
01164 
01165     case CGW_OP_OK:
01166         if (trn == -1) break;     /* invalid transaction number */
01167         /* info(0, "cgw: Got ACK: %s", octstr_get_cstr(clid)); */
01168 
01169         privdata->sendtime[trn] = 0;
01170         privdata->unacked--;
01171 
01172         /* add delivery notification request if wanted */
01173 
01174         msg = privdata->sendmsg[trn];
01175 
01176         if (msg && msg->sms.dlr_url && DLR_IS_ENABLED_DEVICE(msg->sms.dlr_mask)) {
01177             Octstr *ts;
01178 
01179             ts = octstr_create("");
01180             octstr_append(ts, conn->id);
01181             octstr_append_char(ts, '-');
01182             octstr_append_decimal(ts, trn);
01183 
01184             dlr_add(conn->id, ts, msg);
01185 
01186             octstr_destroy(ts);
01187             privdata->dlr[trn] = 1;
01188         } else {
01189             privdata->dlr[trn] = 0;
01190         }
01191 
01192     /* mark as successfully sent */
01193         bb_smscconn_sent(conn, msg, NULL);
01194 
01195         break;
01196 
01197     case CGW_OP_STATUS:
01198         info(0, "CGW: Warning: Got session status");
01199         /* op:status messages are sent by ProviderServer to tell if there are problems with
01200            the session status. These are not wanted, and should never occur, as the delivery is
01201            cancelled, and no end-user billing is done. */
01202 
01203         break;
01204 
01205 
01206     case CGW_OP_HELLO:
01207         info(0, "CGW: Server said: %s", octstr_get_cstr(cgwop_get(cgwop, octstr_imm("hello"))));
01208         break;
01209 
01210     case CGW_OP_ERR:
01211         if (trn == -1) break;     /* invalid transaction number */
01212 
01213         info(0, "CGW: Received error: %s", octstr_get_cstr(txt));
01214 
01215         privdata->sendtime[trn] = 0;
01216         privdata->unacked--;
01217 
01218         bb_smscconn_send_failed(conn, privdata->sendmsg[trn],
01219                             SMSCCONN_FAILED_REJECTED, octstr_create("REJECTED"));
01220 
01221         break;
01222 
01223     default:
01224         info(0, "cgw: Unknown operation: %d", cgwop->op);
01225         return 0;
01226     }
01227 
01228     return 1;
01229 }

Here is the call graph for this function:

void cgw_listener void *  arg  )  [static]
 

Definition at line 967 of file smsc_cgw.c.

References privdata::allow_ip, cgw_receiver(), conn_claim(), conn_destroy(), conn_wrap_fd(), smscconn::data, privdata::deny_ip, error(), gwthread_pollfd(), gwthread_wakeup(), host_ip(), info(), is_allowed_ip(), privdata::listening_socket, smscconn::log_idx, log_thread_to(), octstr_destroy(), octstr_get_cstr, POLLIN, PrivData, privdata::sender_thread, privdata::shutdown, SMSCConn, and warning().

Referenced by smsc_cgw_create().

00968 {
00969     SMSCConn    *conn = arg;
00970     PrivData    *privdata = conn->data;
00971     struct sockaddr_in server_addr;
00972     socklen_t   server_addr_len;
00973     Octstr  *ip;
00974     Connection  *server;
00975     int s, ret;
00976 
00977     /* Make sure we log into our own log-file if defined */
00978     log_thread_to(conn->log_idx);
00979 
00980     while (!privdata->shutdown) {
00981         server_addr_len = sizeof(server_addr);
00982     
00983         ret = gwthread_pollfd(privdata->listening_socket, POLLIN, -1);
00984         if (ret == -1) {
00985             if (errno == EINTR)
00986                 continue;
00987             error(0, "Poll for cgw smsc connections failed, shutting down");
00988             break;
00989         }
00990 
00991         if (privdata->shutdown)
00992             break;
00993         if (ret == 0) /* This thread was woken up from elsewhere, but
00994                        * if we're not shutting down nothing to do here. */
00995             continue;
00996         s = accept(privdata->listening_socket, (struct sockaddr *) & server_addr,
00997                    &server_addr_len);
00998         if (s == -1) {
00999             warning(errno, "cgw_listener: accept() failed, retrying...");
01000             continue;
01001         }
01002 
01003         ip = host_ip(server_addr);
01004         if (!is_allowed_ip(privdata->allow_ip, privdata->deny_ip, ip)) {
01005             info(0, "CGW smsc connection tried from denied host <%s>, disconnected", octstr_get_cstr(ip));
01006             octstr_destroy(ip);
01007             close(s);
01008             continue;
01009         }
01010         server = conn_wrap_fd(s, 0);
01011         if (server == NULL) {
01012             error(0, "cgw_listener: conn_wrap_fd failed on accept()ed fd");
01013             octstr_destroy(ip);
01014             close(s);
01015             continue;
01016         }
01017         conn_claim(server);
01018         info(0, "cgw: smsc connected from %s", octstr_get_cstr(ip));
01019         octstr_destroy(ip);
01020 
01021         cgw_receiver(conn, server);
01022         conn_destroy(server);
01023     }
01024     if (close(privdata->listening_socket) == -1)
01025         warning(errno, "smsc_cgw: couldn't close listening socket at shutdown");
01026     gwthread_wakeup(privdata->sender_thread);
01027 }

Here is the call graph for this function:

int cgw_open_listening_socket SMSCConn conn,
PrivData privdata
[static]
 

Definition at line 945 of file smsc_cgw.c.

References error(), octstr_get_cstr, PrivData, and SMSCConn.

Referenced by smsc_cgw_create().

00946 {
00947     int s;
00948 
00949     if ((s = make_server_socket(privdata->rport, (conn->our_host ? octstr_get_cstr(conn->our_host) : NULL))) == -1) {
00950         error(0, "smsc_cgw: could not create listening socket in port %d", privdata->rport);
00951         return -1;
00952     }
00953     if (socket_set_blocking(s, 0) == -1) {
00954         error(0, "smsc_cgw: couldn't make listening socket port %d non-blocking", privdata->rport);
00955         close(s);
00956         return -1;
00957     }
00958     privdata->listening_socket = s;
00959     return 0;
00960 }

Here is the call graph for this function:

Connection * cgw_open_send_connection SMSCConn conn  )  [static]
 

Definition at line 681 of file smsc_cgw.c.

References bb_smscconn_connected(), bb_smscconn_send_failed(), conn_destroy(), conn_open_tcp_with_port(), smscconn::connect_time, smscconn::data, error(), smscconn::flow_mutex, gwlist_extract_first(), gwthread_sleep(), privdata::host, info(), mutex_lock, mutex_unlock, octstr_get_cstr, smscconn::our_host, privdata::our_port, privdata::outgoing_queue, privdata::port, PrivData, privdata::shutdown, SMSCConn, SMSCCONN_FAILED_TEMPORARILY, and smscconn::status.

Referenced by cgw_sender().

00682 {
00683     PrivData *privdata = conn->data;
00684     int wait;
00685     Connection *server;
00686     Msg *msg;
00687 
00688     wait = 0;
00689     while (!privdata->shutdown) {
00690 
00691         /* Change status only if the first attempt to form a
00692      * connection fails, as it's possible that the SMSC closed the
00693      * connection because of idle timeout and a new one will be
00694      * created quickly. */
00695         if (wait) {
00696             if (conn->status == SMSCCONN_ACTIVE) {
00697                 mutex_lock(conn->flow_mutex);
00698                 conn->status = SMSCCONN_RECONNECTING;
00699                 mutex_unlock(conn->flow_mutex);
00700             }
00701             while ((msg = gwlist_extract_first(privdata->outgoing_queue)))
00702                 bb_smscconn_send_failed(conn, msg, SMSCCONN_FAILED_TEMPORARILY, NULL);
00703             info(0, "smsc_cgw: waiting for %d minutes before trying to connect again", wait);
00704             gwthread_sleep(wait * 60);
00705             wait = wait > 5 ? 10 : wait * 2;
00706         } else
00707             wait = 1;
00708 
00709         server = conn_open_tcp_with_port(privdata->host, privdata->port,
00710                                          privdata->our_port, conn->our_host);
00711 
00712         if (privdata->shutdown) {
00713             conn_destroy(server);
00714             return NULL;
00715         }
00716 
00717         if (server == NULL) {
00718             error(0, "smsc_cgw: opening TCP connection to %s failed", octstr_get_cstr(privdata->host));
00719             continue;
00720         }
00721 
00722         if (conn->status != SMSCCONN_ACTIVE) {
00723             mutex_lock(conn->flow_mutex);
00724             conn->status = SMSCCONN_ACTIVE;
00725             conn->connect_time = time(NULL);
00726             mutex_unlock(conn->flow_mutex);
00727             bb_smscconn_connected(conn);
00728         }
00729         return server;
00730     }
00731     return NULL;
00732 }

Here is the call graph for this function:

long cgw_queued_cb SMSCConn conn  )  [static]
 

Definition at line 599 of file smsc_cgw.c.

References smscconn::data, gwlist_len(), smscconn::load, privdata::outgoing_queue, PrivData, and SMSCConn.

00600 {
00601     PrivData *privdata = conn->data;
00602     long ret = gwlist_len(privdata->outgoing_queue);
00603 
00604     /* use internal queue as load, maybe something else later */
00605 
00606     conn->load = ret;
00607     return ret;
00608 }

Here is the call graph for this function:

struct cgwop * cgw_read_op PrivData privdata,
SMSCConn conn,
Connection server,
time_t  timeout
 

Definition at line 856 of file smsc_cgw.c.

References PrivData, and SMSCConn.

Referenced by cgw_receiver(), and cgw_wait_command().

00857 {
00858     Octstr *line, *name, *value;
00859     int finished = 0;
00860     int c = 0;
00861     struct cgwop *cgwop = NULL;
00862 
00863     int op = CGW_OP_NOP;
00864 
00865     if ((line = conn_read_line(server)) == NULL) 
00866         return NULL;     /* don't block */
00867 
00868     do
00869     {
00870         while (line == NULL)
00871             line = conn_read_line(server);     /* wait for more data */
00872 
00873         c = octstr_search_char(line, ':', 0);
00874         if (c != -1) {
00875             name = octstr_copy(line, 0, c);
00876             value = octstr_copy(line, c + 1, octstr_len(line) - (c + 1));
00877 
00878             if (octstr_compare(name, octstr_imm("hello")) == 0) {
00879                 /* A connection is started by CGW by sending a 
00880          * "hello: Provider Server..." line. */
00881 
00882                 cgwop = cgwop_create(CGW_OP_HELLO, 0);
00883                 cgwop_add(cgwop, octstr_imm("hello"), value);
00884 
00885                 octstr_destroy(name);
00886                 octstr_destroy(value);
00887                 octstr_destroy(line);
00888 
00889                 return cgwop;
00890             }
00891 
00892             if (octstr_compare(name, octstr_imm("op")) == 0) {
00893                 /* check different ops */
00894                 if (octstr_compare(value, octstr_imm("msg")) == 0)
00895                     op = CGW_OP_MSG;
00896                 else
00897                     if (octstr_compare(value, octstr_imm("ok")) == 0)
00898                         op = CGW_OP_OK;
00899                     else
00900                         if (octstr_compare(value, octstr_imm("delivery")) == 0)
00901                             op = CGW_OP_DELIVERY;
00902                         else
00903                             if (octstr_compare(value, octstr_imm("err")) == 0)
00904                                 op = CGW_OP_ERR;
00905                             else
00906                                 if (octstr_compare(value, octstr_imm("status")) == 0)
00907                                     op = CGW_OP_STATUS;
00908                                 else
00909                                     info(0, "CGW: Received unknown op: %s", octstr_get_cstr(value));
00910 
00911                 if (cgwop == NULL)
00912                     cgwop = cgwop_create(op, 0);
00913                 else
00914                     info(0, "cgw: cgwop != null");
00915             }
00916 
00917             if (op != CGW_OP_NOP) {
00918                 /* All commands have to be inside an op:xx ... end:xx statement */
00919 
00920                 if (octstr_compare(name, octstr_imm("end")) == 0) { /* found end of op */
00921                     finished = 1;
00922                 } else {
00923                     /* store in name/value fields in cgwop */
00924                     if (cgwop != NULL) {
00925                         cgwop_add(cgwop, name, value);
00926                     }
00927                 }
00928             }
00929             octstr_destroy(name);
00930             octstr_destroy(value);
00931             octstr_destroy(line);
00932 
00933             if (!finished) line = conn_read_line(server);
00934         } else {
00935             info(0, "cgw: Received invalid input: %s", octstr_get_cstr(line));
00936             octstr_destroy(line);
00937             finished = 1;
00938         }
00939 
00940     } while (!finished);
00941 
00942     return cgwop;
00943 }

void cgw_receiver SMSCConn conn,
Connection server
[static]
 

Definition at line 1029 of file smsc_cgw.c.

References cgw_handle_op(), cgw_read_op(), cgwop_destroy(), conn_eof(), conn_error(), conn_wait(), smscconn::data, error(), info(), smscconn::is_stopped, PrivData, privdata::shutdown, and SMSCConn.

Referenced by cgw_listener().

01030 {
01031     PrivData *privdata = conn->data;
01032     Octstr *str = NULL;
01033     struct cgwop *cgwop;
01034 
01035     while (1) {
01036         if (conn_eof(server)) {
01037             info(0, "cgw: receive connection closed by SMSC");
01038             return ;
01039         }
01040         if (conn_error(server)) {
01041             error(0, "cgw: receive connection broken");
01042             return ;
01043         }
01044         if (conn->is_stopped)
01045         str = NULL;
01046 
01047         cgwop = cgw_read_op(conn->data, conn, server, 0);
01048 
01049         if (cgwop != NULL) {
01050             cgw_handle_op(conn, server, cgwop);
01051             cgwop_destroy(cgwop);
01052         } else
01053             conn_wait(server, -1);
01054 
01055         if (privdata->shutdown)
01056             break;
01057     }
01058     return ;
01059 }

Here is the call graph for this function:

int cgw_send_loop SMSCConn conn,
Connection server
[static]
 

Definition at line 739 of file smsc_cgw.c.

References cgwop_destroy(), cgwop_send(), smscconn::data, gwlist_extract_first(), gwlist_produce(), info(), msg_to_cgwop(), privdata::nexttrn, privdata::outgoing_queue, PrivData, privdata::sendmsg, privdata::sendtime, SMSCConn, and privdata::unacked.

Referenced by cgw_sender().

00740 {
00741     PrivData *privdata = conn->data;
00742     struct cgwop *cgwop;
00743     Msg *msg;
00744     int firsttrn;
00745 
00746     /* Send messages in queue */
00747     while ((msg = gwlist_extract_first(privdata->outgoing_queue)) != NULL) {
00748         firsttrn = privdata->nexttrn;
00749         while (privdata->sendtime[privdata->nexttrn] != 0) { 
00750             if (++privdata->nexttrn >= CGW_TRN_MAX) privdata->nexttrn = 0;    
00751             if (privdata->nexttrn == firsttrn) { /* no available trn */
00752             /* this happens too many messages are sent, and old messages
00753          * haven't been acked. In this case, increase size of 
00754                  * CGW_TRN_MAX */
00755                 info(0, "cgw: Saturated, increase size of CGW_TRN_MAX!");
00756                 gwlist_produce(privdata->outgoing_queue, msg);
00757                 return 1;     /* re-insert, and go check for acks */
00758             }
00759         }
00760 
00761         cgwop = msg_to_cgwop(privdata, msg, privdata->nexttrn);
00762 
00763         if (cgwop == NULL) {
00764             info(0, "cgw: cgwop == NULL");
00765             return 0;
00766         }
00767 
00768         privdata->sendmsg[privdata->nexttrn] = msg;
00769         privdata->sendtime[privdata->nexttrn] = time(NULL);
00770 
00771         if (cgwop_send(server, cgwop) == -1) {
00772             cgwop_destroy(cgwop);
00773             info(0, "cgw: Unable to send (cgwop_send() == -1)");
00774             return -1;
00775         }
00776 
00777         privdata->unacked++;
00778 
00779         cgwop_destroy(cgwop);
00780     }
00781     return 0;
00782 }

Here is the call graph for this function:

void cgw_sender void *  arg  )  [static]
 

Definition at line 616 of file smsc_cgw.c.

References privdata::allow_ip, bb_smscconn_connected(), bb_smscconn_killed(), bb_smscconn_send_failed(), cgw_check_acks(), cgw_open_send_connection(), cgw_send_loop(), cgw_wait_command(), conn_destroy(), smscconn::data, debug(), privdata::deny_ip, error(), smscconn::flow_mutex, gwlist_destroy(), gwlist_extract_first(), gwlist_len(), privdata::host, smscconn::log_idx, log_thread_to(), mutex_lock, mutex_unlock, octstr_destroy(), privdata::outgoing_queue, PrivData, privdata::shutdown, SMSCConn, SMSCCONN_FAILED_SHUTDOWN, and smscconn::status.

Referenced by smsc_cgw_create().

00617 {
00618     SMSCConn *conn = arg;
00619     PrivData *privdata = conn->data;
00620     Msg *msg = NULL;
00621     Connection *server = NULL;
00622     int l = 0;
00623     int ret = 0;
00624 
00625     conn->status = SMSCCONN_CONNECTING;
00626 
00627     /* Make sure we log into our own log-file if defined */
00628     log_thread_to(conn->log_idx);
00629 
00630     while (!privdata->shutdown) {
00631 
00632         /* check that connection is active */
00633         if (conn->status != SMSCCONN_ACTIVE) {
00634             if ((server = cgw_open_send_connection(conn)) == NULL) {
00635                 privdata->shutdown = 1;
00636                 error(0, "Unable to connect to CGW server");
00637                 return ;
00638             }
00639 
00640             conn->status = SMSCCONN_ACTIVE;
00641             bb_smscconn_connected(conn);
00642         } else {
00643         ret = 0;
00644             l = gwlist_len(privdata->outgoing_queue);
00645             if (l > 0)
00646                ret = cgw_send_loop(conn, server);     /* send any messages in queue */
00647 
00648             if (ret != -1) ret = cgw_wait_command(privdata, conn, server, 1);     /* read ack's and delivery reports */
00649             if (ret != -1) cgw_check_acks(privdata);     /* check un-acked messages */
00650  
00651             if (ret == -1) {
00652                 mutex_lock(conn->flow_mutex);
00653                 conn->status = SMSCCONN_RECONNECTING;
00654                 mutex_unlock(conn->flow_mutex);
00655         }
00656         }
00657     }
00658 
00659     conn_destroy(server);
00660 
00661     while ((msg = gwlist_extract_first(privdata->outgoing_queue)) != NULL)
00662         bb_smscconn_send_failed(conn, msg, SMSCCONN_FAILED_SHUTDOWN, NULL);
00663     mutex_lock(conn->flow_mutex);
00664 
00665     conn->status = SMSCCONN_DEAD;
00666 
00667     gwlist_destroy(privdata->outgoing_queue, NULL);
00668     octstr_destroy(privdata->host);
00669     octstr_destroy(privdata->allow_ip);
00670     octstr_destroy(privdata->deny_ip);
00671 
00672     gw_free(privdata);
00673     conn->data = NULL;
00674 
00675     mutex_unlock(conn->flow_mutex);
00676     debug("bb.sms", 0, "smsc_cgw connection has completed shutdown.");
00677     bb_smscconn_killed();
00678 }

Here is the call graph for this function:

int cgw_shutdown_cb SMSCConn conn,
int  finish_sending
[static]
 

Definition at line 562 of file smsc_cgw.c.

References bb_smscconn_send_failed(), smscconn::data, debug(), gwlist_extract_first(), gwthread_wakeup(), privdata::outgoing_queue, PrivData, privdata::receiver_thread, privdata::rport, privdata::shutdown, SMSCConn, SMSCCONN_FAILED_SHUTDOWN, and smscconn::why_killed.

00563 {
00564     PrivData *privdata = conn->data;
00565 
00566     debug("bb.sms", 0, "Shutting down SMSCConn CGW, %s",
00567           finish_sending ? "slow" : "instant");
00568 
00569     /* Documentation claims this would have been done by smscconn.c,
00570        but isn't when this code is being written. */
00571     conn->why_killed = SMSCCONN_KILLED_SHUTDOWN;
00572     privdata->shutdown = 1;     /* Separate from why_killed to avoid locking, as
00573                          * why_killed may be changed from outside? */
00574 
00575     if (finish_sending == 0) {
00576         Msg *msg;
00577         while ((msg = gwlist_extract_first(privdata->outgoing_queue)) != NULL) {
00578             bb_smscconn_send_failed(conn, msg, SMSCCONN_FAILED_SHUTDOWN, NULL);
00579         }
00580     }
00581 
00582     if (privdata->rport > 0)
00583         gwthread_wakeup(privdata->receiver_thread);
00584     return 0;
00585 }

Here is the call graph for this function:

void cgw_start_cb SMSCConn conn  )  [static]
 

Definition at line 588 of file smsc_cgw.c.

References smscconn::data, debug(), gwthread_wakeup(), PrivData, privdata::receiver_thread, privdata::rport, and SMSCConn.

00589 {
00590     PrivData *privdata = conn->data;
00591 
00592     /* in case there are messages in the buffer already */
00593     if (privdata->rport > 0)
00594         gwthread_wakeup(privdata->receiver_thread);
00595     debug("smsc.cgw", 0, "smsc_cgw: start called");
00596 }

Here is the call graph for this function:

int cgw_wait_command PrivData privdata,
SMSCConn conn,
Connection server,
int  timeout
 

Definition at line 811 of file smsc_cgw.c.

References cgw_handle_op(), cgw_read_op(), cgwop_destroy(), conn_eof(), conn_error(), conn_wait(), error(), gwthread_pollfd(), info(), POLLIN, PrivData, privdata::send_socket, SMSCConn, SMSCCONN_DISCONNECTED, and smscconn::status.

Referenced by cgw_sender().

00812 {
00813     int ret;
00814     struct cgwop *cgwop;
00815 
00816     /* is there data to be read? */
00817     ret = gwthread_pollfd(privdata->send_socket, POLLIN, 0.2); 
00818     
00819     if (ret != -1) {
00820         /* read all waiting ops */
00821     cgwop = cgw_read_op(privdata, conn, server, timeout);
00822         if (cgwop != NULL) {
00823         do {
00824         if (conn_eof(server)) {
00825             info(0, "cgw: Connection closed by SMSC");
00826             conn->status = SMSCCONN_DISCONNECTED;
00827             if (cgwop != NULL) cgwop_destroy(cgwop);
00828             return -1;
00829         }
00830         if (conn_error(server)) {
00831             error(0, "cgw: Error trying to read ACKs from SMSC");
00832             if (cgwop != NULL) cgwop_destroy(cgwop);
00833             return -1;
00834         }
00835 
00836         cgw_handle_op(conn, server, cgwop);
00837         cgwop_destroy(cgwop);
00838         } while ((cgwop = cgw_read_op(privdata, conn, server, timeout)) != NULL);
00839     } else 
00840         conn_wait(server, 1); /* added because gwthread_pollfd
00841                      seems to always return 1. This will keep
00842                      the load on a reasonable level */
00843     }
00844 
00845     return 0;
00846 }

Here is the call graph for this function:

void cgwop_add struct cgwop cgwop,
Octstr name,
Octstr value
[static]
 

Definition at line 199 of file smsc_cgw.c.

References info(), name, cgwop::name, cgwop::num_fields, octstr_duplicate, and cgwop::value.

Referenced by cgw_handle_op(), cgwop_create(), and msg_to_cgwop().

00200 {
00201     if (cgwop->num_fields < CGWOP_MAXARGS)
00202     {
00203         cgwop->name[cgwop->num_fields] = octstr_duplicate(name);
00204         cgwop->value[cgwop->num_fields] = octstr_duplicate(value);
00205 
00206         cgwop->num_fields++;
00207     } else
00208     {
00209         info(0, "cgw: CGWOP_MAXARGS exceeded.");
00210     }
00211 }

Here is the call graph for this function:

struct cgwop* cgwop_create int  op,
int  trn
[static]
 

Definition at line 214 of file smsc_cgw.c.

References cgwop_add(), CGWOP_MAXARGS, cgwop::name, cgwop::num_fields, Octstr, octstr_append_decimal(), octstr_create, octstr_destroy(), octstr_imm(), cgwop::op, cgwop::trn, and cgwop::value.

Referenced by cgw_handle_op(), and msg_to_cgwop().

00215 {
00216     struct cgwop *ret;
00217     Octstr *trnstr;
00218 
00219     ret = gw_malloc(sizeof(struct cgwop));
00220 
00221     ret->op = op;
00222     ret->num_fields = 0;
00223     ret->trn = trn;
00224 
00225     ret->name = gw_malloc(CGWOP_MAXARGS * sizeof(Octstr *));
00226     ret->value = gw_malloc(CGWOP_MAXARGS * sizeof(Octstr *));
00227 
00228     if (trn != -1)
00229     {
00230         trnstr = octstr_create("");
00231         octstr_append_decimal(trnstr, trn);
00232         cgwop_add(ret, octstr_imm("client-id"), trnstr);
00233         octstr_destroy(trnstr);
00234     }
00235 
00236     return ret;
00237 }

Here is the call graph for this function:

void cgwop_destroy struct cgwop cgwop  )  [static]
 

Definition at line 239 of file smsc_cgw.c.

References cgwop::name, cgwop::num_fields, octstr_destroy(), and cgwop::value.

Referenced by cgw_handle_op(), cgw_receiver(), cgw_send_loop(), and cgw_wait_command().

00240 {
00241     int len;
00242 
00243     len = cgwop->num_fields;
00244     while (--len >= 0)
00245     {
00246         octstr_destroy(cgwop->name[len]);      /* octstr_destroy(NULL) is ok */
00247         octstr_destroy(cgwop->value[len]);
00248     }
00249 
00250     gw_free(cgwop->name);
00251     gw_free(cgwop->value);
00252     gw_free(cgwop);
00253 }

Here is the call graph for this function:

Octstr* cgwop_get struct cgwop cgwop,
Octstr name
[static]
 

Definition at line 255 of file smsc_cgw.c.

References cgwop::name, name, cgwop::num_fields, octstr_compare(), and cgwop::value.

Referenced by cgw_handle_op().

00256 {
00257     int len = cgwop->num_fields;
00258 
00259     while (--len >= 0)
00260         if (octstr_compare(name, cgwop->name[len]) == 0)
00261             return cgwop->value[len];
00262     return NULL;
00263 }

Here is the call graph for this function:

int cgwop_send Connection conn,
struct cgwop cgwop
[static]
 

Definition at line 292 of file smsc_cgw.c.

References cgwop_tostr(), conn_write(), and octstr_destroy().

Referenced by cgw_handle_op(), and cgw_send_loop().

00293 {
00294     Octstr *dta = cgwop_tostr(cgwop);
00295 
00296     if (dta == NULL) return -1;     /* couldn't convert to string */
00297 
00298     if (conn_write(conn, dta) == -1)
00299     {
00300         octstr_destroy(dta);
00301         return -1;
00302     }
00303 
00304     octstr_destroy(dta);
00305     return 1;
00306 }

Here is the call graph for this function:

Octstr* cgwop_tostr struct cgwop cgwop  )  [static]
 

Definition at line 265 of file smsc_cgw.c.

References CGW_EOL, cgw_ops, cgwop::name, cgwop::num_fields, octstr_append(), octstr_append_char(), octstr_create, octstr_imm(), cgwop::op, and cgwop::value.

Referenced by cgwop_send().

00266 {
00267     int len = cgwop->num_fields;
00268     Octstr *str;
00269 
00270     if (cgw_ops[cgwop->op] == NULL) return NULL;     /* invalid operation */
00271 
00272     str = octstr_create("");
00273 
00274     octstr_append(str, octstr_imm("op:"));
00275     octstr_append(str, octstr_imm(cgw_ops[cgwop->op]));
00276     octstr_append_char(str, CGW_EOL);
00277 
00278     while (--len >= 0)
00279     {
00280         octstr_append(str, cgwop->name[len]);
00281         octstr_append_char(str, ':');
00282         octstr_append(str, cgwop->value[len]);
00283         octstr_append_char(str, CGW_EOL);
00284     }
00285     octstr_append(str, octstr_imm("end:"));
00286     octstr_append(str, octstr_imm(cgw_ops[cgwop->op]));
00287     octstr_append_char(str, CGW_EOL);
00288 
00289     return str;
00290 }

Here is the call graph for this function:

struct cgwop* msg_to_cgwop PrivData privdata,
Msg msg,
int  trn
[static]
 

Definition at line 380 of file smsc_cgw.c.

References privdata::appname, cgw_encode_msg(), CGW_OP_MSG, cgwop_add(), cgwop_create(), DLR_IS_ENABLED_DEVICE, gw_isdigit(), octstr_append(), octstr_binary_to_hex(), octstr_check_range(), octstr_create, octstr_destroy(), octstr_duplicate, octstr_imm(), octstr_len(), and PrivData.

Referenced by cgw_send_loop().

00381 {
00382     struct cgwop *cgwop;
00383     Octstr *sender, *udh, *dta;
00384 
00385     cgwop = cgwop_create(CGW_OP_MSG, trn);
00386 
00387     if (cgwop == NULL) return NULL;
00388 
00389     if (!octstr_check_range(msg->sms.sender, 0, octstr_len(msg->sms.sender), gw_isdigit))
00390     {
00391         /* If alphanumeric, simply prefix sender with '$' char */
00392         sender = octstr_create("$");
00393         octstr_append(sender, msg->sms.sender);
00394     } else sender = octstr_duplicate(msg->sms.sender);
00395 
00396     cgwop_add(cgwop, octstr_imm("app"), privdata->appname);
00397     cgwop_add(cgwop, octstr_imm("from"), sender);
00398     cgwop_add(cgwop, octstr_imm("to"), msg->sms.receiver);
00399 
00400     /* If delivery reports are asked, ask for them by adding a nrq:anything field */
00401     if (DLR_IS_ENABLED_DEVICE(msg->sms.dlr_mask))
00402         cgwop_add(cgwop, octstr_imm("nrq"), octstr_imm("true"));
00403 
00404     octstr_destroy(sender);
00405 
00406     if (octstr_len(msg->sms.udhdata))
00407     {
00408         udh = octstr_duplicate(msg->sms.udhdata);
00409         octstr_binary_to_hex(udh, 1);
00410         cgwop_add(cgwop, octstr_imm("udh"), udh);
00411         octstr_destroy(udh);
00412 
00413         dta = octstr_duplicate(msg->sms.msgdata);
00414         octstr_binary_to_hex(dta, 1);
00415         cgwop_add(cgwop, octstr_imm("msg"), dta);
00416         cgwop_add(cgwop, octstr_imm("type"), octstr_imm("bin"));
00417         octstr_destroy(dta);
00418     } else
00419     {
00420         cgwop_add(cgwop, octstr_imm("msg"), cgw_encode_msg(msg->sms.msgdata));
00421     }
00422 
00423     return cgwop;
00424 }

Here is the call graph for this function:

int smsc_cgw_create SMSCConn conn,
CfgGroup cfg
 

Definition at line 431 of file smsc_cgw.c.

References privdata::allow_ip, privdata::appname, cfg_get, cfg_get_integer(), CGW_DEFPORT, cgw_listener(), cgw_open_listening_socket(), cgw_sender(), privdata::check_time, smscconn::connect_time, smscconn::data, privdata::deny_ip, privdata::dlr, error(), gwlist_create, gwlist_destroy(), gwthread_create, privdata::host, info(), privdata::listening_socket, smscconn::name, privdata::nexttrn, octstr_create, octstr_destroy(), octstr_format(), octstr_imm(), privdata::our_port, privdata::outgoing_queue, privdata::port, PrivData, smscconn::queued, privdata::receiver_thread, privdata::rport, smscconn::send_msg, privdata::sender_thread, privdata::sendtime, privdata::shutdown, smscconn::shutdown, SMSCConn, smscconn::start_conn, smscconn::status, privdata::waitack, and smscconn::why_killed.

Referenced by smscconn_create().

00432 {
00433     PrivData *privdata;
00434     Octstr *allow_ip, *deny_ip, *host, *appname;
00435     long portno, our_port, waitack;
00436     int i;
00437 
00438     privdata = gw_malloc(sizeof(PrivData));
00439     privdata->outgoing_queue = gwlist_create();
00440     privdata->listening_socket = -1;
00441 
00442     if (cfg_get_integer(&portno, cfg, octstr_imm("port")) == -1)
00443         portno = 0;
00444     privdata->port = portno;
00445 
00446     if (cfg_get_integer(&portno, cfg, octstr_imm("receive-port")) < 0)
00447         portno = 0;
00448     privdata->rport = portno;
00449 
00450     host = cfg_get(cfg, octstr_imm("host"));
00451     appname = cfg_get(cfg, octstr_imm("appname"));
00452 
00453     if (cfg_get_integer(&our_port, cfg, octstr_imm("our-port")) == -1)
00454         privdata->our_port = 0;     /* 0 means use any port */
00455     else
00456         privdata->our_port = our_port;
00457 
00458     allow_ip = cfg_get(cfg, octstr_imm("connect-allow-ip"));
00459     if (allow_ip)
00460         deny_ip = octstr_create("*.*.*.*");
00461     else
00462         deny_ip = NULL;
00463 
00464     if (cfg_get_integer(&waitack, cfg, octstr_imm("wait-ack")) < 0)
00465         privdata->waitack = 60;
00466     else
00467         privdata->waitack = waitack;
00468 
00469     if (privdata->port <= 0 || privdata->port > 65535) {
00470         info(1, "No port defined for cgw -> using default (%d)", CGW_DEFPORT);
00471         privdata->port = CGW_DEFPORT;
00472     }
00473 
00474 
00475     if (host == NULL) {
00476         error(0, "'host' missing in cgw configuration.");
00477         goto error;
00478     }
00479 
00480     if (appname == NULL)
00481         appname = octstr_create("send");
00482 
00483     privdata->allow_ip = allow_ip;
00484     privdata->deny_ip = deny_ip;
00485     privdata->host = host;
00486     privdata->appname = appname;
00487     privdata->nexttrn = 0;
00488     privdata->check_time = 0;
00489 
00490     for (i = 0; i < CGW_TRN_MAX; i++) {
00491         privdata->sendtime[i] = 0;
00492         privdata->dlr[i] = 0;
00493     }
00494 
00495     if (privdata->rport > 0 && cgw_open_listening_socket(conn,privdata) < 0) {
00496         gw_free(privdata);
00497         privdata = NULL;
00498         goto error;
00499     }
00500 
00501 
00502     conn->data = privdata;
00503 
00504     conn->name = octstr_format("CGW:%d", privdata->port);
00505 
00506     privdata->shutdown = 0;
00507 
00508     conn->status = SMSCCONN_CONNECTING;
00509     conn->connect_time = time(NULL);
00510 
00511     if (privdata->rport > 0 && (privdata->receiver_thread = gwthread_create(cgw_listener, conn)) == -1)
00512         goto error;
00513 
00514     if ((privdata->sender_thread = gwthread_create(cgw_sender, conn)) == -1) {
00515         privdata->shutdown = 1;
00516         goto error;
00517     }
00518 
00519     conn->shutdown = cgw_shutdown_cb;
00520     conn->queued = cgw_queued_cb;
00521     conn->start_conn = cgw_start_cb;
00522     conn->send_msg = cgw_add_msg_cb;
00523 
00524     return 0;
00525 
00526 error:
00527     error(0, "Failed to create CGW smsc connection");
00528     if (privdata != NULL)
00529         gwlist_destroy(privdata->outgoing_queue, NULL);
00530 
00531     gw_free(privdata);
00532     octstr_destroy(host);
00533     octstr_destroy(allow_ip);
00534     octstr_destroy(deny_ip);
00535     octstr_destroy(appname);
00536 
00537     conn->why_killed = SMSCCONN_KILLED_CANNOT_CONNECT;
00538     conn->status = SMSCCONN_DEAD;
00539     info(0, "exiting");
00540     return -1;
00541 }

Here is the call graph for this function:


Variable Documentation

char* cgw_ops[6] = {"nop", "msg", "ok", "err", "delivery", "hello"} [static]
 

Definition at line 148 of file smsc_cgw.c.

Referenced by cgwop_tostr().

See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.