Kannel: Open Source WAP and SMS gateway  $Revision: 5037 $
smsc_http.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 "urltrans.h"
#include "meta_data.h"
#include "http/generic.c"
#include "http/brunet.c"
#include "http/xidris.c"
#include "http/clickatell.c"

Go to the source code of this file.

Data Structures

struct  smsc_http_fn_callbacks
 
struct  conndata
 

Macros

#define DEFAULT_CHARSET   "UTF-8"
 
#define DEFAULT_UCS2_CHARSET   "UTF-16BE"
 

Typedefs

typedef struct conndata ConnData
 

Enumerations

enum  { HEX_NOT_UPPERCASE = 0 }
 

Functions

static void conndata_destroy (ConnData *conndata)
 
static void httpsmsc_receiver (void *arg)
 
static void httpsmsc_sender (void *arg)
 
static void httpsmsc_send_cb (void *arg)
 
static int kannel_send_sms (SMSCConn *conn, Msg *sms)
 
static void kannel_parse_reply (SMSCConn *conn, Msg *msg, int status, List *headers, Octstr *body)
 
static void kannel_receive_sms (SMSCConn *conn, HTTPClient *client, List *headers, Octstr *body, List *cgivars)
 
static int httpsmsc_send (SMSCConn *conn, Msg *msg)
 
static long httpsmsc_queued (SMSCConn *conn)
 
static int httpsmsc_shutdown (SMSCConn *conn, int finish_sending)
 
int smsc_http_create (SMSCConn *conn, CfgGroup *cfg)
 

Variables

struct smsc_http_fn_callbacks smsc_http_kannel_callback
 

Macro Definition Documentation

◆ DEFAULT_CHARSET

#define DEFAULT_CHARSET   "UTF-8"

Definition at line 131 of file smsc_http.c.

Referenced by httpsmsc_send().

◆ DEFAULT_UCS2_CHARSET

#define DEFAULT_UCS2_CHARSET   "UTF-16BE"

Definition at line 132 of file smsc_http.c.

Referenced by httpsmsc_send().

Typedef Documentation

◆ ConnData

typedef struct conndata ConnData

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
HEX_NOT_UPPERCASE 

Definition at line 493 of file smsc_http.c.

Function Documentation

◆ conndata_destroy()

static void conndata_destroy ( ConnData conndata)
static

Definition at line 175 of file smsc_http.c.

References conndata::allow_ip, conndata::alt_charset, counter_destroy(), conndata::dlr_url, gwlist_destroy(), http_caller_destroy(), conndata::http_ref, conndata::max_pending_sends, conndata::msg_to_send, octstr_destroy(), conndata::open_sends, conndata::password, conndata::proxy, semaphore_destroy(), conndata::send_url, conndata::system_id, and conndata::username.

Referenced by httpsmsc_receiver(), httpsmsc_sender(), and smsc_http_create().

176 {
177  if (conndata == NULL)
178  return;
179  if (conndata->http_ref)
180  http_caller_destroy(conndata->http_ref);
181  octstr_destroy(conndata->allow_ip);
182  octstr_destroy(conndata->send_url);
183  octstr_destroy(conndata->dlr_url);
184  octstr_destroy(conndata->username);
185  octstr_destroy(conndata->password);
186  octstr_destroy(conndata->proxy);
187  octstr_destroy(conndata->system_id);
188  octstr_destroy(conndata->alt_charset);
189  counter_destroy(conndata->open_sends);
190  gwlist_destroy(conndata->msg_to_send, NULL);
191  if (conndata->max_pending_sends)
193 
194  gw_free(conndata);
195 }
Octstr * dlr_url
Definition: smsc_http.c:152
Octstr * alt_charset
Definition: smsc_http.c:162
void counter_destroy(Counter *counter)
Definition: counter.c:110
HTTPCaller * http_ref
Definition: smsc_http.c:144
Octstr * allow_ip
Definition: smsc_http.c:150
Octstr * proxy
Definition: smsc_http.c:161
Octstr * system_id
Definition: smsc_http.c:157
Counter * open_sends
Definition: smsc_http.c:153
List * msg_to_send
Definition: smsc_http.c:163
void semaphore_destroy(Semaphore *semaphore)
Definition: semaphore.c:104
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
Semaphore * max_pending_sends
Definition: smsc_http.c:154
Octstr * password
Definition: smsc_http.c:156
Octstr * username
Definition: smsc_http.c:155
void http_caller_destroy(HTTPCaller *caller)
Definition: http.c:907
Octstr * send_url
Definition: smsc_http.c:151
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)
Definition: list.c:145

◆ httpsmsc_queued()

static long httpsmsc_queued ( SMSCConn conn)
static

Definition at line 859 of file smsc_http.c.

References smscconn::data, gwlist_len(), smscconn::load, conndata::msg_to_send, SMSCCONN_DEAD, and smscconn::status.

Referenced by smsc_http_create().

860 {
861  ConnData *conndata = conn->data;
862 
863  conn->load = (conndata ? (conn->status != SMSCCONN_DEAD ?
864  gwlist_len(conndata->msg_to_send) : 0) : 0);
865 
866  return conn->load;
867 }
long gwlist_len(List *list)
Definition: list.c:166
void * data
Definition: smscconn_p.h:249
List * msg_to_send
Definition: smsc_http.c:163
smscconn_status_t status
Definition: smscconn_p.h:151
int load
Definition: smscconn_p.h:152

◆ httpsmsc_receiver()

static void httpsmsc_receiver ( void *  arg)
static

Definition at line 201 of file smsc_http.c.

References conndata::allow_ip, bb_smscconn_killed(), conndata::callbacks, client(), conndata_destroy(), connect_denied(), counter_value(), smscconn::data, debug(), smsc_http_fn_callbacks::destroy, smscconn::flow_mutex, gwthread_join(), gwthread_wakeup(), http_accept_request(), http_caller_signal_shutdown(), http_cgivar_dump_into(), http_close_client(), http_close_port(), http_destroy_cgiargs(), http_destroy_headers(), conndata::http_ref, smscconn::id, info(), smscconn::log_idx, log_thread_to(), mutex_lock, mutex_unlock, octstr_append_char(), octstr_destroy(), octstr_get_cstr, conndata::open_sends, conndata::port, smsc_http_fn_callbacks::receive_sms, conndata::send_cb_thread, conndata::sender_thread, conndata::shutdown, SMSCCONN_DEAD, smscconn::status, and url.

Referenced by smsc_http_create().

202 {
203  SMSCConn *conn = arg;
204  ConnData *conndata = conn->data;
206  Octstr *ip, *url, *body;
207  List *headers, *cgivars;
208 
209  /* Make sure we log into our own log-file if defined */
210  log_thread_to(conn->log_idx);
211 
212  while (conndata->shutdown == 0) {
213  /* reset */
214  ip = url = body = NULL;
215  headers = cgivars = NULL;
216 
217  /* XXX if conn->is_stopped, do not receive new messages.. */
218 
219  client = http_accept_request(conndata->port, &ip, &url,
220  &headers, &body, &cgivars);
221  if (client == NULL)
222  break;
223 
224  if (cgivars != NULL) {
225  octstr_append_char(url, '?');
226  http_cgivar_dump_into(cgivars, url);
227  }
228 
229  debug("smsc.http", 0, "HTTP[%s]: Got request `%s'",
230  octstr_get_cstr(conn->id), octstr_get_cstr(url));
231 
232  if (connect_denied(conndata->allow_ip, ip)) {
233  info(0, "HTTP[%s]: Connection `%s' tried from denied "
234  "host %s, ignored", octstr_get_cstr(conn->id),
235  octstr_get_cstr(url), octstr_get_cstr(ip));
236  http_close_client(client);
237  } else
238  conndata->callbacks->receive_sms(conn, client, headers, body, cgivars);
239 
240  debug("smsc.http", 0, "HTTP[%s]: Destroying client information",
241  octstr_get_cstr(conn->id));
242  octstr_destroy(url);
243  octstr_destroy(ip);
244  octstr_destroy(body);
245  http_destroy_headers(headers);
246  http_destroy_cgiargs(cgivars);
247  }
248  debug("smsc.http", 0, "HTTP[%s]: httpsmsc_receiver dying",
249  octstr_get_cstr(conn->id));
250 
251  conndata->shutdown = 1;
252  http_close_port(conndata->port);
253 
254  /* unblock http_receive_result() if there are no open sends */
255  if (counter_value(conndata->open_sends) == 0)
257 
258  if (conndata->sender_thread != -1) {
259  gwthread_wakeup(conndata->sender_thread);
260  gwthread_join(conndata->sender_thread);
261  }
262  if (conndata->send_cb_thread != -1) {
263  gwthread_wakeup(conndata->send_cb_thread);
264  gwthread_join(conndata->send_cb_thread);
265  }
266 
267  mutex_lock(conn->flow_mutex);
268  conn->status = SMSCCONN_DEAD;
269  mutex_unlock(conn->flow_mutex);
270 
271  if (conndata->callbacks != NULL && conndata->callbacks->destroy != NULL)
272  conndata->callbacks->destroy(conn);
273  conn->data = NULL;
274  conndata_destroy(conndata);
276 }
void info(int err, const char *fmt,...)
Definition: log.c:672
static void conndata_destroy(ConnData *conndata)
Definition: smsc_http.c:175
void http_caller_signal_shutdown(HTTPCaller *caller)
Definition: http.c:913
#define mutex_unlock(m)
Definition: thread.h:136
void http_close_client(HTTPClient *client)
Definition: http.c:2735
void bb_smscconn_killed(void)
Definition: bb_smscconn.c:199
Octstr * id
Definition: smscconn_p.h:174
void gwthread_join(long thread)
void * data
Definition: smscconn_p.h:249
static void client(int port)
Definition: test_udp.c:77
HTTPCaller * http_ref
Definition: smsc_http.c:144
void octstr_append_char(Octstr *ostr, int ch)
Definition: octstr.c:1515
int log_idx
Definition: smscconn_p.h:197
Octstr * allow_ip
Definition: smsc_http.c:150
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
void(* destroy)(SMSCConn *conn)
Definition: smsc_http.c:137
int connect_denied(Octstr *allow_ip, Octstr *ip)
Definition: utils.c:833
void log_thread_to(int idx)
Definition: log.c:759
void http_destroy_headers(List *headers)
Definition: http.c:2856
volatile int shutdown
Definition: smsc_http.c:148
void http_destroy_cgiargs(List *args)
Definition: http.c:2795
long port
Definition: smsc_http.c:149
Counter * open_sends
Definition: smsc_http.c:153
HTTPClient * http_accept_request(int port, Octstr **client_ip, Octstr **url, List **headers, Octstr **body, List **cgivars)
Definition: http.c:2575
void http_close_port(int port)
Definition: http.c:2505
Mutex * flow_mutex
Definition: smscconn_p.h:157
long sender_thread
Definition: smsc_http.c:147
void http_cgivar_dump_into(List *cgiargs, Octstr *os)
Definition: http.c:3436
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
unsigned long counter_value(Counter *counter)
Definition: counter.c:145
Definition: octstr.c:118
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
void gwthread_wakeup(long thread)
smscconn_status_t status
Definition: smscconn_p.h:151
void(* receive_sms)(SMSCConn *conn, HTTPClient *client, List *headers, Octstr *body, List *cgivars)
Definition: smsc_http.c:140
static Octstr * url
Definition: test_xmlrpc.c:84
#define mutex_lock(m)
Definition: thread.h:130
struct smsc_http_fn_callbacks * callbacks
Definition: smsc_http.c:168
Definition: list.c:102
long send_cb_thread
Definition: smsc_http.c:146

◆ httpsmsc_send()

static int httpsmsc_send ( SMSCConn conn,
Msg msg 
)
static

Definition at line 811 of file smsc_http.c.

References conndata::alt_charset, conndata::callbacks, charset_convert(), smscconn::data, DC_7BIT, DC_UCS2, DC_UNDEF, DEFAULT_CHARSET, DEFAULT_UCS2_CHARSET, error(), gwlist_produce(), msg_duplicate(), conndata::msg_to_send, octstr_get_cstr, and smsc_http_fn_callbacks::send_sms.

Referenced by smsc_http_create().

812 {
813  ConnData *conndata = conn->data;
814  Msg *sms;
815 
816 
817  /* don't crash if no send_sms handle defined */
818  if (!conndata || !conndata->callbacks->send_sms)
819  return -1;
820 
821  sms = msg_duplicate(msg);
822  /* convert character encoding if required */
823  if (conndata->alt_charset) {
824  /*
825  * Converted now to the target character set based on the
826  * one we got in the msg, which is either UTF-8 (our normal
827  * inter-box encoding), but may also be UCS-2, so beware.
828  * In addition, IF we convert to an "extra" encoding here
829  * we also revert the .coding vaue to DC_UNDEF, in order
830  * that all API specific code doesn't indicate an encoding
831  * which is no longer inside the payload here.
832  */
833  if (sms->sms.coding == DC_7BIT) {
834  if (charset_convert(sms->sms.msgdata, DEFAULT_CHARSET,
835  octstr_get_cstr(conndata->alt_charset)) == 0) {
836  sms->sms.coding = DC_UNDEF;
837  } else {
838  error(0, "Failed to convert msgdata from charset <%s> to <%s>, will send as is.",
840  }
841  }
842  else if (sms->sms.coding == DC_UCS2) {
843  if (charset_convert(sms->sms.msgdata, DEFAULT_UCS2_CHARSET,
844  octstr_get_cstr(conndata->alt_charset)) == 0) {
845  sms->sms.coding = DC_UNDEF;
846  } else {
847  error(0, "Failed to convert msgdata from charset <%s> to <%s>, will send as is.",
849  }
850  }
851  }
852 
853  gwlist_produce(conndata->msg_to_send, sms);
854 
855  return 0;
856 }
void error(int err, const char *fmt,...)
Definition: log.c:648
#define DEFAULT_CHARSET
Definition: smsc_http.c:131
Msg * msg_duplicate(Msg *msg)
Definition: msg.c:111
Octstr * alt_charset
Definition: smsc_http.c:162
int(* send_sms)(SMSCConn *conn, Msg *msg)
Definition: smsc_http.c:138
void gwlist_produce(List *list, void *item)
Definition: list.c:411
void * data
Definition: smscconn_p.h:249
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
Definition: msg.h:79
List * msg_to_send
Definition: smsc_http.c:163
#define DEFAULT_UCS2_CHARSET
Definition: smsc_http.c:132
#define DC_UNDEF
Definition: sms.h:109
struct smsc_http_fn_callbacks * callbacks
Definition: smsc_http.c:168
#define DC_UCS2
Definition: sms.h:112
int charset_convert(Octstr *string, char *charset_from, char *charset_to)
Definition: charset.c:589
#define DC_7BIT
Definition: sms.h:110

◆ httpsmsc_send_cb()

static void httpsmsc_send_cb ( void *  arg)
static

Definition at line 352 of file smsc_http.c.

References bb_smscconn_connected(), bb_smscconn_send_failed(), conndata::callbacks, smscconn::connect_time, counter_decrease(), counter_value(), smscconn::data, debug(), error(), smscconn::flow_mutex, gwthread_sleep(), http_destroy_headers(), http_receive_result, conndata::http_ref, smscconn::id, smscconn::log_idx, log_thread_to(), conndata::max_pending_sends, msg, mutex_lock, mutex_unlock, octstr_destroy(), octstr_get_cstr, conndata::open_sends, smsc_http_fn_callbacks::parse_reply, smscconn::reconnect_delay, semaphore_up(), conndata::shutdown, SMSCCONN_ACTIVE, SMSCCONN_FAILED_SHUTDOWN, SMSCCONN_FAILED_TEMPORARILY, SMSCCONN_RECONNECTING, smscconn::status, and warning().

Referenced by smsc_http_create().

353 {
354  SMSCConn *conn = arg;
355  ConnData *conndata = conn->data;
356  Msg *msg;
357  int status;
358  List *headers;
359  Octstr *final_url, *body;
360 
361  /* Make sure we log into our own log-file if defined */
362  log_thread_to(conn->log_idx);
363 
364  while(conndata->shutdown == 0 || counter_value(conndata->open_sends)) {
365 
366  msg = http_receive_result(conndata->http_ref, &status,
367  &final_url, &headers, &body);
368 
369  if (msg == NULL)
370  break; /* they told us to die, by unlocking */
371 
372  counter_decrease(conndata->open_sends);
373  if (conndata->max_pending_sends)
374  semaphore_up(conndata->max_pending_sends);
375 
376  /* Handle various states here. */
377 
378  /* request failed and we are not in shutdown mode */
379  if (status == -1 && conndata->shutdown == 0) {
380  error(0, "HTTP[%s]: Couldn't connect to SMS center."
381  "(retrying in %ld seconds) %ld.",
382  octstr_get_cstr(conn->id), conn->reconnect_delay, counter_value(conndata->open_sends));
383  mutex_lock(conn->flow_mutex);
385  mutex_unlock(conn->flow_mutex);
386  /* XXX how should we know whether it's temp. error ?? */
388  /*
389  * Just sleep reconnect delay and set conn to ACTIVE again;
390  * otherwise if no pending request are here, we leave conn in
391  * RECONNECTING state for ever and no routing (trials) take place.
392  */
393  if (counter_value(conndata->open_sends) == 0) {
395  /* and now enable routing again */
396  mutex_lock(conn->flow_mutex);
397  conn->status = SMSCCONN_ACTIVE;
398  time(&conn->connect_time);
399  mutex_unlock(conn->flow_mutex);
400  /* tell bearerbox core that we are connected again */
401  bb_smscconn_connected(conn);
402  }
403  continue;
404  }
405  /* request failed and we *are* in shutdown mode, drop the message */
406  else if (status == -1 && conndata->shutdown == 1) {
408  }
409  /* request succeeded */
410  else {
411  /* we received a response, so this link is considered online again */
412  if (conn->status != SMSCCONN_ACTIVE) {
413  mutex_lock(conn->flow_mutex);
414  conn->status = SMSCCONN_ACTIVE;
415  time(&conn->connect_time);
416  mutex_unlock(conn->flow_mutex);
417  /* tell bearerbox core that we are connected again */
418  bb_smscconn_connected(conn);
419  }
420  conndata->callbacks->parse_reply(conn, msg, status, headers, body);
421  }
422 
423  http_destroy_headers(headers);
424  octstr_destroy(final_url);
425  octstr_destroy(body);
426  }
427  debug("smsc.http", 0, "HTTP[%s]: httpsmsc_send_cb dying",
428  octstr_get_cstr(conn->id));
429  conndata->shutdown = 1;
430 
431  if (counter_value(conndata->open_sends)) {
432  warning(0, "HTTP[%s]: Shutdown while <%ld> requests are pending.",
433  octstr_get_cstr(conn->id), counter_value(conndata->open_sends));
434  }
435 }
void error(int err, const char *fmt,...)
Definition: log.c:648
void bb_smscconn_connected(SMSCConn *conn)
Definition: bb_smscconn.c:192
void semaphore_up(Semaphore *semaphore)
Definition: semaphore.c:118
#define mutex_unlock(m)
Definition: thread.h:136
Octstr * id
Definition: smscconn_p.h:174
void * data
Definition: smscconn_p.h:249
HTTPCaller * http_ref
Definition: smsc_http.c:144
int log_idx
Definition: smscconn_p.h:197
void(* parse_reply)(SMSCConn *conn, Msg *msg, int status, List *headers, Octstr *body)
Definition: smsc_http.c:139
unsigned long counter_decrease(Counter *counter)
Definition: counter.c:155
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
long reconnect_delay
Definition: smscconn_p.h:199
void log_thread_to(int idx)
Definition: log.c:759
void http_destroy_headers(List *headers)
Definition: http.c:2856
volatile int shutdown
Definition: smsc_http.c:148
Counter * open_sends
Definition: smsc_http.c:153
Definition: msg.h:79
time_t connect_time
Definition: smscconn_p.h:155
Mutex * flow_mutex
Definition: smscconn_p.h:157
void warning(int err, const char *fmt,...)
Definition: log.c:660
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
unsigned long counter_value(Counter *counter)
Definition: counter.c:145
void gwthread_sleep(double seconds)
Semaphore * max_pending_sends
Definition: smsc_http.c:154
#define http_receive_result(caller, status, final_url, headers, body)
Definition: http.h:383
Definition: octstr.c:118
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
smscconn_status_t status
Definition: smscconn_p.h:151
void bb_smscconn_send_failed(SMSCConn *conn, Msg *sms, int reason, Octstr *reply)
Definition: bb_smscconn.c:328
#define mutex_lock(m)
Definition: thread.h:130
struct smsc_http_fn_callbacks * callbacks
Definition: smsc_http.c:168
Definition: list.c:102
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86

◆ httpsmsc_sender()

static void httpsmsc_sender ( void *  arg)
static

Definition at line 282 of file smsc_http.c.

References bb_smscconn_killed(), bb_smscconn_send_failed(), conndata::callbacks, conndata_destroy(), counter_decrease(), counter_increase(), counter_value(), smscconn::data, delay, smsc_http_fn_callbacks::destroy, smscconn::flow_mutex, gwlist_consume(), gwlist_extract_first(), gwthread_join(), gwthread_sleep(), gwthread_wakeup(), http_caller_signal_shutdown(), conndata::http_ref, smscconn::log_idx, log_thread_to(), conndata::max_pending_sends, msg, conndata::msg_to_send, mutex_lock, mutex_unlock, conndata::open_sends, conndata::port, semaphore_down(), semaphore_up(), conndata::send_cb_thread, smsc_http_fn_callbacks::send_sms, conndata::shutdown, SMSCCONN_DEAD, SMSCCONN_FAILED_SHUTDOWN, smscconn::status, and smscconn::throughput.

Referenced by smsc_http_create().

283 {
284  SMSCConn *conn = arg;
285  ConnData *conndata = conn->data;
286  Msg *msg;
287  double delay = 0;
288 
289  /* Make sure we log into our own log-file if defined */
290  log_thread_to(conn->log_idx);
291 
292  if (conn->throughput) {
293  delay = 1.0 / conn->throughput;
294  }
295 
296  while (conndata->shutdown == 0) {
297  /* check if we can send ; otherwise block on semaphore */
298  if (conndata->max_pending_sends)
300 
301  if (conndata->shutdown) {
302  if (conndata->max_pending_sends)
303  semaphore_up(conndata->max_pending_sends);
304  break;
305  }
306 
307  msg = gwlist_consume(conndata->msg_to_send);
308  if (msg == NULL)
309  break;
310 
311  /* obey throughput speed limit, if any */
312  if (conn->throughput > 0) {
313  gwthread_sleep(delay);
314  }
315  counter_increase(conndata->open_sends);
316  if (conndata->callbacks->send_sms(conn, msg) == -1) {
317  counter_decrease(conndata->open_sends);
318  if (conndata->max_pending_sends)
319  semaphore_up(conndata->max_pending_sends);
320  }
321  }
322 
323  /* put outstanding sends back into global queue */
324  while((msg = gwlist_extract_first(conndata->msg_to_send)))
326 
327  /* if there no receiver shutdown */
328  if (conndata->port <= 0) {
329  /* unblock http_receive_result() if there are no open sends */
330  if (counter_value(conndata->open_sends) == 0)
332 
333  if (conndata->send_cb_thread != -1) {
334  gwthread_wakeup(conndata->send_cb_thread);
335  gwthread_join(conndata->send_cb_thread);
336  }
337  mutex_lock(conn->flow_mutex);
338  conn->status = SMSCCONN_DEAD;
339  mutex_unlock(conn->flow_mutex);
340 
341  if (conndata->callbacks != NULL && conndata->callbacks->destroy != NULL)
342  conndata->callbacks->destroy(conn);
343  conn->data = NULL;
344  conndata_destroy(conndata);
346  }
347 }
static void conndata_destroy(ConnData *conndata)
Definition: smsc_http.c:175
void semaphore_up(Semaphore *semaphore)
Definition: semaphore.c:118
int(* send_sms)(SMSCConn *conn, Msg *msg)
Definition: smsc_http.c:138
void http_caller_signal_shutdown(HTTPCaller *caller)
Definition: http.c:913
#define mutex_unlock(m)
Definition: thread.h:136
void bb_smscconn_killed(void)
Definition: bb_smscconn.c:199
void gwthread_join(long thread)
void * data
Definition: smscconn_p.h:249
HTTPCaller * http_ref
Definition: smsc_http.c:144
int log_idx
Definition: smscconn_p.h:197
void semaphore_down(Semaphore *semaphore)
Definition: semaphore.c:132
unsigned long counter_decrease(Counter *counter)
Definition: counter.c:155
void(* destroy)(SMSCConn *conn)
Definition: smsc_http.c:137
unsigned long counter_increase(Counter *counter)
Definition: counter.c:123
void log_thread_to(int idx)
Definition: log.c:759
volatile int shutdown
Definition: smsc_http.c:148
long port
Definition: smsc_http.c:149
Counter * open_sends
Definition: smsc_http.c:153
Definition: msg.h:79
List * msg_to_send
Definition: smsc_http.c:163
void * gwlist_extract_first(List *list)
Definition: list.c:305
double throughput
Definition: smscconn_p.h:203
Mutex * flow_mutex
Definition: smscconn_p.h:157
static double delay
Definition: mtbatch.c:99
unsigned long counter_value(Counter *counter)
Definition: counter.c:145
void gwthread_sleep(double seconds)
Semaphore * max_pending_sends
Definition: smsc_http.c:154
void * gwlist_consume(List *list)
Definition: list.c:427
void gwthread_wakeup(long thread)
smscconn_status_t status
Definition: smscconn_p.h:151
void bb_smscconn_send_failed(SMSCConn *conn, Msg *sms, int reason, Octstr *reply)
Definition: bb_smscconn.c:328
#define mutex_lock(m)
Definition: thread.h:130
struct smsc_http_fn_callbacks * callbacks
Definition: smsc_http.c:168
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
long send_cb_thread
Definition: smsc_http.c:146

◆ httpsmsc_shutdown()

static int httpsmsc_shutdown ( SMSCConn conn,
int  finish_sending 
)
static

Definition at line 870 of file smsc_http.c.

References smscconn::data, debug(), smscconn::flow_mutex, gwlist_remove_producer(), gwthread_wakeup(), http_close_port(), smscconn::id, conndata::msg_to_send, mutex_lock, mutex_unlock, octstr_get_cstr, conndata::port, conndata::receive_thread, conndata::sender_thread, conndata::shutdown, SMSCCONN_KILLED_SHUTDOWN, and smscconn::why_killed.

Referenced by smsc_http_create().

871 {
872  ConnData *conndata = conn->data;
873 
874  if (conndata == NULL)
875  return 0;
876 
877  debug("httpsmsc_shutdown", 0, "HTTP[%s]: Shutting down",
878  octstr_get_cstr(conn->id));
879 
880  mutex_lock(conn->flow_mutex);
882 
883  conndata->shutdown = 1;
884 
885  if (conndata->port > 0)
886  http_close_port(conndata->port);
888  if (conndata->receive_thread != -1)
889  gwthread_wakeup(conndata->receive_thread);
890  if (conndata->sender_thread != -1)
891  gwthread_wakeup(conndata->sender_thread);
892  mutex_unlock(conn->flow_mutex);
893 
894  return 0;
895 }
long receive_thread
Definition: smsc_http.c:145
#define mutex_unlock(m)
Definition: thread.h:136
Octstr * id
Definition: smscconn_p.h:174
void * data
Definition: smscconn_p.h:249
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
smscconn_killed_t why_killed
Definition: smscconn_p.h:153
volatile int shutdown
Definition: smsc_http.c:148
long port
Definition: smsc_http.c:149
List * msg_to_send
Definition: smsc_http.c:163
void http_close_port(int port)
Definition: http.c:2505
void gwlist_remove_producer(List *list)
Definition: list.c:401
Mutex * flow_mutex
Definition: smscconn_p.h:157
long sender_thread
Definition: smsc_http.c:147
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
void gwthread_wakeup(long thread)
#define mutex_lock(m)
Definition: thread.h:130

◆ kannel_parse_reply()

static void kannel_parse_reply ( SMSCConn conn,
Msg msg,
int  status,
List headers,
Octstr body 
)
static

Definition at line 599 of file smsc_http.c.

References bb_smscconn_send_failed(), bb_smscconn_sent(), dlr_add(), DLR_IS_ENABLED_DEVICE, HTTP_ACCEPTED, HTTP_OK, smscconn::id, octstr_case_compare(), octstr_create, octstr_destroy(), octstr_duplicate, octstr_imm(), octstr_ncompare(), SMSCCONN_FAILED_MALFORMED, UUID_STR_LEN, and uuid_unparse().

601 {
602  /* Test on three cases:
603  * 1. an smsbox reply of an remote kannel instance
604  * 2. an smsc_http response (if used for MT to MO looping)
605  * 3. an smsbox reply of partly successful sendings */
606  if ((status == HTTP_OK || status == HTTP_ACCEPTED)
607  && (octstr_case_compare(body, octstr_imm("0: Accepted for delivery")) == 0 ||
608  octstr_case_compare(body, octstr_imm("Sent.")) == 0 ||
609  octstr_case_compare(body, octstr_imm("Ok.")) == 0 ||
610  octstr_ncompare(body, octstr_imm("Result: OK"),10) == 0)) {
611  char id[UUID_STR_LEN + 1];
612  Octstr *mid;
613 
614  /* create Octstr from UUID */
615  uuid_unparse(msg->sms.id, id);
616  mid = octstr_create(id);
617 
618  /* add to our own DLR storage */
619  if (DLR_IS_ENABLED_DEVICE(msg->sms.dlr_mask))
620  dlr_add(conn->id, mid, msg, 0);
621 
622  octstr_destroy(mid);
623 
624  bb_smscconn_sent(conn, msg, NULL);
625  } else {
626  bb_smscconn_send_failed(conn, msg,
628  }
629 }
Octstr * id
Definition: smscconn_p.h:174
void uuid_unparse(const uuid_t uu, char *out)
Definition: gw_uuid.c:562
void dlr_add(const Octstr *smsc, const Octstr *ts, Msg *msg, int use_dst)
Definition: dlr.c:330
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:281
Definition: http.h:142
int octstr_ncompare(const Octstr *ostr1, const Octstr *ostr2, long n)
Definition: octstr.c:950
#define octstr_duplicate(ostr)
Definition: octstr.h:187
int octstr_case_compare(const Octstr *os1, const Octstr *os2)
Definition: octstr.c:901
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
#define octstr_create(cstr)
Definition: octstr.h:125
#define UUID_STR_LEN
Definition: gw_uuid.h:19
Definition: octstr.c:118
void bb_smscconn_sent(SMSCConn *conn, Msg *sms, Octstr *reply)
Definition: bb_smscconn.c:279
void bb_smscconn_send_failed(SMSCConn *conn, Msg *sms, int reason, Octstr *reply)
Definition: bb_smscconn.c:328
#define DLR_IS_ENABLED_DEVICE(dlr)
Definition: dlr.h:82

◆ kannel_receive_sms()

static void kannel_receive_sms ( SMSCConn conn,
HTTPClient client,
List headers,
Octstr body,
List cgivars 
)
static

Definition at line 632 of file smsc_http.c.

References account, bb_smscconn_receive(), charset, smscconn::data, debug(), dlr_find(), error(), from, gwlist_create, HTTP_ACCEPTED, http_cgi_variable(), http_destroy_headers(), http_header_add(), http_send_reply(), smscconn::id, MAX_SMS_OCTETS, meta_data_set_value(), METADATA_DLR_GROUP, METADATA_DLR_GROUP_ERRORCODE, msg, msg_create, octstr_compare(), octstr_create, octstr_destroy(), octstr_duplicate, octstr_get_char(), octstr_get_cstr, octstr_imm(), octstr_len(), conndata::password, report_mo, sms_charset_processing(), SMS_PARAM_UNDEFINED, text, and conndata::username.

634 {
635  ConnData *conndata = conn->data;
636  Octstr *user, *pass, *from, *to, *text, *udh, *account, *binfo, *charset;
637  Octstr *dlrmid, *dlrerr;
638  Octstr *tmp_string, *retmsg;
639  int mclass, mwi, coding, validity, deferred, dlrmask;
640  List *reply_headers;
641  int ret;
642 
643  mclass = mwi = coding = validity =
644  deferred = dlrmask = SMS_PARAM_UNDEFINED;
645 
646  user = http_cgi_variable(cgivars, "username");
647  pass = http_cgi_variable(cgivars, "password");
648  from = http_cgi_variable(cgivars, "from");
649  to = http_cgi_variable(cgivars, "to");
650  text = http_cgi_variable(cgivars, "text");
651  udh = http_cgi_variable(cgivars, "udh");
652  charset = http_cgi_variable(cgivars, "charset");
653  account = http_cgi_variable(cgivars, "account");
654  binfo = http_cgi_variable(cgivars, "binfo");
655  dlrmid = http_cgi_variable(cgivars, "dlr-mid");
656  tmp_string = http_cgi_variable(cgivars, "flash");
657  if (tmp_string) {
658  sscanf(octstr_get_cstr(tmp_string),"%d", &mclass);
659  }
660  tmp_string = http_cgi_variable(cgivars, "mclass");
661  if (tmp_string) {
662  sscanf(octstr_get_cstr(tmp_string),"%d", &mclass);
663  }
664  tmp_string = http_cgi_variable(cgivars, "mwi");
665  if (tmp_string) {
666  sscanf(octstr_get_cstr(tmp_string),"%d", &mwi);
667  }
668  tmp_string = http_cgi_variable(cgivars, "coding");
669  if (tmp_string) {
670  sscanf(octstr_get_cstr(tmp_string),"%d", &coding);
671  }
672  tmp_string = http_cgi_variable(cgivars, "validity");
673  if (tmp_string) {
674  sscanf(octstr_get_cstr(tmp_string),"%d", &validity);
675  }
676  tmp_string = http_cgi_variable(cgivars, "deferred");
677  if (tmp_string) {
678  sscanf(octstr_get_cstr(tmp_string),"%d", &deferred);
679  }
680  tmp_string = http_cgi_variable(cgivars, "dlr-mask");
681  if (tmp_string) {
682  sscanf(octstr_get_cstr(tmp_string),"%d", &dlrmask);
683  }
684  dlrerr = http_cgi_variable(cgivars, "dlr-err");
685 
686  debug("smsc.http.kannel", 0, "HTTP[%s]: Received an HTTP request",
687  octstr_get_cstr(conn->id));
688 
689  if (user == NULL || pass == NULL ||
690  octstr_compare(user, conndata->username) != 0 ||
691  octstr_compare(pass, conndata->password) != 0) {
692 
693  error(0, "HTTP[%s]: Authorization failure",
694  octstr_get_cstr(conn->id));
695  retmsg = octstr_create("Authorization failed for sendsms");
696  } else if (dlrmask != 0 && dlrmid != NULL) {
697  /* we got a DLR, and we don't require additional values */
698  Msg *dlrmsg;
699 
700  dlrmsg = dlr_find(conn->id,
701  dlrmid, /* message id */
702  to, /* destination */
703  dlrmask, 0);
704 
705  if (dlrmsg != NULL) {
706  dlrmsg->sms.sms_type = report_mo;
707  dlrmsg->sms.msgdata = octstr_duplicate(text);
708  dlrmsg->sms.account = octstr_duplicate(conndata->username);
709 
710  debug("smsc.http.kannel", 0, "HTTP[%s]: Received DLR for DLR-URL <%s>",
711  octstr_get_cstr(conn->id), octstr_get_cstr(dlrmsg->sms.dlr_url));
712 
713  if (dlrerr != NULL) {
714  /* pass errorcode as is */
715  if (dlrmsg->sms.meta_data == NULL)
716  dlrmsg->sms.meta_data = octstr_create("");
717 
718  meta_data_set_value(dlrmsg->sms.meta_data, METADATA_DLR_GROUP,
720  }
721 
722  ret = bb_smscconn_receive(conn, dlrmsg);
723  if (ret == -1)
724  retmsg = octstr_create("Not accepted");
725  else
726  retmsg = octstr_create("Sent.");
727  } else {
728  error(0,"HTTP[%s]: Got DLR but could not find message or was not interested "
729  "in it id<%s> dst<%s>, type<%d>",
730  octstr_get_cstr(conn->id), octstr_get_cstr(dlrmid),
731  octstr_get_cstr(to), dlrmask);
732  retmsg = octstr_create("Unknown DLR, not accepted");
733  }
734  }
735  else if (from == NULL || to == NULL || text == NULL) {
736 
737  error(0, "HTTP[%s]: Insufficient args",
738  octstr_get_cstr(conn->id));
739  retmsg = octstr_create("Insufficient args, rejected");
740  }
741  else if (udh != NULL && (octstr_len(udh) != octstr_get_char(udh, 0) + 1)) {
742  error(0, "HTTP[%s]: UDH field misformed, rejected",
743  octstr_get_cstr(conn->id));
744  retmsg = octstr_create("UDH field misformed, rejected");
745  }
746  else if (udh != NULL && octstr_len(udh) > MAX_SMS_OCTETS) {
747  error(0, "HTTP[%s]: UDH field is too long, rejected",
748  octstr_get_cstr(conn->id));
749  retmsg = octstr_create("UDH field is too long, rejected");
750  }
751  else {
752  /* we got a normal MO SMS */
753  Msg *msg;
754  msg = msg_create(sms);
755 
756  debug("smsc.http.kannel", 0, "HTTP[%s]: Constructing new SMS",
757  octstr_get_cstr(conn->id));
758 
759  msg->sms.service = octstr_duplicate(user);
760  msg->sms.sender = octstr_duplicate(from);
761  msg->sms.receiver = octstr_duplicate(to);
762  msg->sms.msgdata = octstr_duplicate(text);
763  msg->sms.udhdata = octstr_duplicate(udh);
764 
765  msg->sms.smsc_id = octstr_duplicate(conn->id);
766  msg->sms.time = time(NULL);
767  msg->sms.mclass = mclass;
768  msg->sms.mwi = mwi;
769  msg->sms.coding = coding;
770  msg->sms.validity = (validity == SMS_PARAM_UNDEFINED ? validity : time(NULL) + validity * 60);
771  msg->sms.deferred = (deferred == SMS_PARAM_UNDEFINED ? deferred : time(NULL) + deferred * 60);
772  msg->sms.account = octstr_duplicate(account);
773  msg->sms.binfo = octstr_duplicate(binfo);
774 
775  /* re-encode content if necessary */
776  if (sms_charset_processing(charset, msg->sms.msgdata, msg->sms.coding) == -1) {
777  error(0, "HTTP[%s]: Charset or body misformed, rejected",
778  octstr_get_cstr(conn->id));
779  retmsg = octstr_create("Charset or body misformed, rejected");
780  }
781  else {
782 
783  ret = bb_smscconn_receive(conn, msg);
784  if (ret == -1)
785  retmsg = octstr_create("Not accepted");
786  else
787  retmsg = octstr_create("Sent.");
788  }
789  }
790 
791  reply_headers = gwlist_create();
792  http_header_add(reply_headers, "Content-Type", "text/plain");
793  debug("smsc.http.kannel", 0, "HTTP[%s]: Sending reply",
794  octstr_get_cstr(conn->id));
795  http_send_reply(client, HTTP_ACCEPTED, reply_headers, retmsg);
796 
797  octstr_destroy(retmsg);
798  http_destroy_headers(reply_headers);
799 }
void error(int err, const char *fmt,...)
Definition: log.c:648
#define MAX_SMS_OCTETS
Definition: sms.h:129
void http_header_add(List *headers, char *name, char *contents)
Definition: http.c:2863
Definition: msg.h:109
Octstr * id
Definition: smscconn_p.h:174
void * data
Definition: smscconn_p.h:249
#define METADATA_DLR_GROUP_ERRORCODE
Definition: meta_data.h:71
int meta_data_set_value(Octstr *data, const char *group, const Octstr *key, const Octstr *value, int replace)
Definition: meta_data.c:324
#define msg_create(type)
Definition: msg.h:136
Msg * dlr_find(const Octstr *smsc, const Octstr *ts, const Octstr *dst, int typ, int use_dst)
Definition: dlr.c:387
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
Octstr * charset
Definition: test_ota.c:68
Octstr * http_cgi_variable(List *list, char *name)
Definition: http.c:2813
void http_destroy_headers(List *headers)
Definition: http.c:2856
static Octstr * from
Definition: mtbatch.c:95
void http_send_reply(HTTPClient *client, int status, List *headers, Octstr *body)
Definition: http.c:2672
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:281
Definition: msg.h:79
long bb_smscconn_receive(SMSCConn *conn, Msg *sms)
Definition: bb_smscconn.c:478
char * text
Definition: smsc_cimd2.c:921
#define METADATA_DLR_GROUP
Definition: meta_data.h:68
#define octstr_duplicate(ostr)
Definition: octstr.h:187
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
int sms_charset_processing(Octstr *charset, Octstr *body, int coding)
Definition: sms.c:419
#define octstr_create(cstr)
Definition: octstr.h:125
#define SMS_PARAM_UNDEFINED
Definition: sms.h:91
long octstr_len(const Octstr *ostr)
Definition: octstr.c:340
Definition: octstr.c:118
Octstr * password
Definition: smsc_http.c:156
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
#define gwlist_create()
Definition: list.h:136
Octstr * username
Definition: smsc_http.c:155
int octstr_get_char(const Octstr *ostr, long pos)
Definition: octstr.c:404
Definition: list.c:102
static Octstr * account
Definition: mtbatch.c:94
static XMLRPCDocument * msg
Definition: test_xmlrpc.c:86
int octstr_compare(const Octstr *ostr1, const Octstr *ostr2)
Definition: octstr.c:869

◆ kannel_send_sms()

static int kannel_send_sms ( SMSCConn conn,
Msg sms 
)
static

Definition at line 496 of file smsc_http.c.

References smscconn::data, DC_7BIT, DC_UCS2, DC_UNDEF, debug(), DLR_NOTHING, DLR_UNDEFINED, conndata::dlr_url, gwlist_create, HEX_NOT_UPPERCASE, http_destroy_headers(), HTTP_METHOD_GET, conndata::http_ref, http_start_request(), smscconn::id, MC_UNDEF, MWI_UNDEF, conndata::no_coding, conndata::no_sender, conndata::no_sep, octstr_append_cstr(), octstr_binary_to_hex(), octstr_create, octstr_destroy(), octstr_duplicate, octstr_format(), octstr_format_append(), octstr_get_cstr, octstr_imm(), octstr_len(), conndata::password, conndata::send_url, SMS_PARAM_UNDEFINED, url, conndata::username, UUID_STR_LEN, and uuid_unparse().

497 {
498  ConnData *conndata = conn->data;
499  Octstr *url;
500  List *headers;
501 
502  if (!conndata->no_sep) {
503  url = octstr_format("%S?"
504  "username=%E&password=%E&to=%E&text=%E",
505  conndata->send_url,
506  conndata->username, conndata->password,
507  sms->sms.receiver, sms->sms.msgdata);
508  } else {
509  Octstr *msgdata = octstr_duplicate(sms->sms.msgdata);
510 
512  url = octstr_format("%S?"
513  "username=%E&password=%E&to=%E&text=%S",
514  conndata->send_url,
515  conndata->username, conndata->password,
516  sms->sms.receiver, msgdata);
517  octstr_destroy(msgdata);
518  }
519 
520  if (octstr_len(sms->sms.udhdata)) {
521  if (!conndata->no_sep) {
522  octstr_format_append(url, "&udh=%E", sms->sms.udhdata);
523  } else {
524  Octstr *udhdata = octstr_duplicate(sms->sms.udhdata);
525 
527  octstr_format_append(url, "&udh=%S", udhdata);
528  octstr_destroy(udhdata);
529  }
530  }
531 
532  if (!conndata->no_sender)
533  octstr_format_append(url, "&from=%E", sms->sms.sender);
534  if (sms->sms.mclass != MC_UNDEF)
535  octstr_format_append(url, "&mclass=%d", sms->sms.mclass);
536  if (!conndata->no_coding && sms->sms.coding != DC_UNDEF)
537  octstr_format_append(url, "&coding=%d", sms->sms.coding);
538 
539  /* Obey that smsbox's sendsms HTTP interface is still expecting
540  * WINDOWS-1252 as default charset, while all other internal parts
541  * use UTF-8 as internal encoding. This means, when we pass a SMS
542  * into a next Kannel instance, we need to let the smsbox know which
543  * charset we have in use.
544  * XXX TODO: change smsbox interface to use UTF-8 as default
545  * in next major release. */
546  if (sms->sms.coding == DC_7BIT)
547  octstr_append_cstr(url, "&charset=UTF-8");
548  else if (sms->sms.coding == DC_UCS2)
549  octstr_append_cstr(url, "&charset=UTF-16BE");
550 
551  if (sms->sms.mwi != MWI_UNDEF)
552  octstr_format_append(url, "&mwi=%d", sms->sms.mwi);
553  if (sms->sms.account) /* prepend account with local username */
554  octstr_format_append(url, "&account=%E:%E", sms->sms.service, sms->sms.account);
555  if (sms->sms.binfo) /* prepend billing info */
556  octstr_format_append(url, "&binfo=%S", sms->sms.binfo);
557  if (sms->sms.smsc_id) /* proxy the smsc-id to the next instance */
558  octstr_format_append(url, "&smsc=%S", sms->sms.smsc_id);
559  if (conndata->dlr_url) {
560  char id[UUID_STR_LEN + 1];
561  Octstr *mid;
562 
563  /* create Octstr from UUID */
564  uuid_unparse(sms->sms.id, id);
565  mid = octstr_create(id);
566 
567  octstr_format_append(url, "&dlr-url=%E", conndata->dlr_url);
568 
569  /* encapsulate the original DLR-URL, escape code for DLR mask
570  * and message id */
571  octstr_format_append(url, "%E%E%E%E%E",
572  octstr_imm("&dlr-url="), sms->sms.dlr_url != NULL ? sms->sms.dlr_url : octstr_imm(""),
573  octstr_imm("&dlr-mask=%d"),
574  octstr_imm("&dlr-mid="), mid);
575 
576  octstr_destroy(mid);
577  } else if (sms->sms.dlr_url != NULL)
578  octstr_format_append(url, "&dlr-url=%E", sms->sms.dlr_url);
579  if (sms->sms.dlr_mask != DLR_UNDEFINED && sms->sms.dlr_mask != DLR_NOTHING)
580  octstr_format_append(url, "&dlr-mask=%d", sms->sms.dlr_mask);
581 
582  if (sms->sms.validity != SMS_PARAM_UNDEFINED)
583  octstr_format_append(url, "&validity=%ld", (sms->sms.validity - time(NULL)) / 60);
584  if (sms->sms.deferred != SMS_PARAM_UNDEFINED)
585  octstr_format_append(url, "&deferred=%ld", (sms->sms.deferred - time(NULL)) / 60);
586 
587  headers = gwlist_create();
588  debug("smsc.http.kannel", 0, "HTTP[%s]: Start request",
589  octstr_get_cstr(conn->id));
590  http_start_request(conndata->http_ref, HTTP_METHOD_GET, url, headers,
591  NULL, 0, sms, NULL);
592 
593  octstr_destroy(url);
594  http_destroy_headers(headers);
595 
596  return 0;
597 }
#define MWI_UNDEF
Definition: sms.h:99
Octstr * dlr_url
Definition: smsc_http.c:152
int no_sep
Definition: smsc_http.c:160
Octstr * id
Definition: smscconn_p.h:174
void * data
Definition: smscconn_p.h:249
HTTPCaller * http_ref
Definition: smsc_http.c:144
#define DLR_NOTHING
Definition: dlr.h:71
void uuid_unparse(const uuid_t uu, char *out)
Definition: gw_uuid.c:562
void octstr_append_cstr(Octstr *ostr, const char *cstr)
Definition: octstr.c:1509
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
void octstr_binary_to_hex(Octstr *ostr, int uppercase)
Definition: octstr.c:463
void http_destroy_headers(List *headers)
Definition: http.c:2856
void http_start_request(HTTPCaller *caller, int method, Octstr *url, List *headers, Octstr *body, int follow, void *id, Octstr *certkeyfile)
Definition: http.c:1745
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:281
int no_coding
Definition: smsc_http.c:159
#define octstr_duplicate(ostr)
Definition: octstr.h:187
Octstr * octstr_format(const char *fmt,...)
Definition: octstr.c:2462
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
#define octstr_create(cstr)
Definition: octstr.h:125
#define SMS_PARAM_UNDEFINED
Definition: sms.h:91
int no_sender
Definition: smsc_http.c:158
#define UUID_STR_LEN
Definition: gw_uuid.h:19
#define DLR_UNDEFINED
Definition: dlr.h:70
long octstr_len(const Octstr *ostr)
Definition: octstr.c:340
#define MC_UNDEF
Definition: sms.h:93
Definition: octstr.c:118
Octstr * password
Definition: smsc_http.c:156
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
void octstr_format_append(Octstr *os, const char *fmt,...)
Definition: octstr.c:2505
#define gwlist_create()
Definition: list.h:136
Octstr * username
Definition: smsc_http.c:155
#define DC_UNDEF
Definition: sms.h:109
Octstr * send_url
Definition: smsc_http.c:151
static Octstr * url
Definition: test_xmlrpc.c:84
Definition: list.c:102
#define DC_UCS2
Definition: sms.h:112
#define DC_7BIT
Definition: sms.h:110

◆ smsc_http_create()

int smsc_http_create ( SMSCConn conn,
CfgGroup cfg 
)

Definition at line 904 of file smsc_http.c.

References conndata::allow_ip, conndata::alt_charset, conndata::callbacks, cfg_get, cfg_get_bool(), cfg_get_integer(), conndata_destroy(), smscconn::connect_time, counter_create(), conndata::data, smscconn::data, smsc_http_fn_callbacks::destroy, conndata::dlr_url, error(), gwlist_add_producer(), gwlist_create, gwthread_create, http_caller_create(), http_open_port(), conndata::http_ref, httpsmsc_queued(), httpsmsc_receiver(), httpsmsc_send(), httpsmsc_send_cb(), httpsmsc_sender(), httpsmsc_shutdown(), smscconn::id, info(), smsc_http_fn_callbacks::init, conndata::max_pending_sends, conndata::msg_to_send, smscconn::name, conndata::no_coding, conndata::no_sender, conndata::no_sep, octstr_case_compare(), octstr_destroy(), octstr_format(), octstr_get_cstr, octstr_imm(), conndata::open_sends, panic, conndata::password, conndata::port, conndata::proxy, smscconn::queued, conndata::receive_thread, semaphore_create(), conndata::send_cb_thread, smscconn::send_msg, conndata::send_url, conndata::sender_thread, conndata::shutdown, smscconn::shutdown, smsc_http_brunet_callback, smsc_http_clickatell_callback, smsc_http_generic_callback, smsc_http_kannel_callback, smsc_http_xidris_callback, SMSCCONN_ACTIVE, SMSCCONN_ACTIVE_RECV, SMSCCONN_DEAD, SMSCCONN_KILLED_CANNOT_CONNECT, ssl, smscconn::status, conndata::system_id, type, conndata::username, warning(), and smscconn::why_killed.

Referenced by smscconn_create().

905 {
906  ConnData *conndata = NULL;
907  Octstr *type;
908  int ssl = 0; /* indicate if SSL-enabled server should be used */
909  long max_ps;
910 
911  if ((type = cfg_get(cfg, octstr_imm("system-type"))) == NULL) {
912  error(0, "HTTP[%s]: 'system-type' missing in smsc 'http' record.",
913  octstr_get_cstr(conn->id));
914  octstr_destroy(type);
915  return -1;
916  }
917 
918  conndata = gw_malloc(sizeof(ConnData));
919  /* reset conndata */
920  memset(conndata, 0, sizeof(ConnData));
921 
922  conn->data = conndata;
923  conndata->http_ref = NULL;
924  conndata->data = NULL;
925 
926  if (cfg_get_integer(&conndata->port, cfg, octstr_imm("port")) == -1) {
927  warning(0, "HTTP[%s]: 'port' not set in smsc 'http' group.",
928  octstr_get_cstr(conn->id));
929  conndata->port = -1;
930  }
931 
932  conndata->allow_ip = cfg_get(cfg, octstr_imm("connect-allow-ip"));
933  conndata->send_url = cfg_get(cfg, octstr_imm("send-url"));
934  conndata->username = cfg_get(cfg, octstr_imm("smsc-username"));
935  conndata->password = cfg_get(cfg, octstr_imm("smsc-password"));
936  conndata->system_id = cfg_get(cfg, octstr_imm("system-id"));
937  cfg_get_bool(&conndata->no_sender, cfg, octstr_imm("no-sender"));
938  cfg_get_bool(&conndata->no_coding, cfg, octstr_imm("no-coding"));
939  cfg_get_bool(&conndata->no_sep, cfg, octstr_imm("no-sep"));
940  conndata->proxy = cfg_get(cfg, octstr_imm("system-id"));
941  cfg_get_bool(&ssl, cfg, octstr_imm("use-ssl"));
942  conndata->dlr_url = cfg_get(cfg, octstr_imm("dlr-url"));
943  conndata->alt_charset = cfg_get(cfg, octstr_imm("alt-charset"));
944 
945  if (cfg_get_integer(&max_ps, cfg, octstr_imm("max-pending-submits")) == -1 || max_ps < 1)
946  max_ps = 10;
947 
948  conndata->max_pending_sends = semaphore_create(max_ps);
949 
950  if (conndata->port <= 0 && conndata->send_url == NULL) {
951  error(0, "Sender and receiver disabled. Dummy SMSC not allowed.");
952  goto error;
953  }
954  if (conndata->send_url == NULL)
955  panic(0, "HTTP[%s]: Sending not allowed. No 'send-url' specified.",
956  octstr_get_cstr(conn->id));
957 
958  if (octstr_case_compare(type, octstr_imm("kannel")) == 0) {
959  if (conndata->username == NULL || conndata->password == NULL) {
960  error(0, "HTTP[%s]: 'username' and 'password' required for Kannel http smsc",
961  octstr_get_cstr(conn->id));
962  goto error;
963  }
965  } else if (octstr_case_compare(type, octstr_imm("brunet")) == 0) {
967  } else if (octstr_case_compare(type, octstr_imm("xidris")) == 0) {
969  } else if (octstr_case_compare(type, octstr_imm("generic")) == 0) {
971  } else if (octstr_case_compare(type, octstr_imm("clickatell")) == 0) {
973  }
974  /*
975  * ADD NEW HTTP SMSC TYPES HERE
976  */
977  else {
978  error(0, "HTTP[%s]: system-type '%s' unknown smsc 'http' record.",
979  octstr_get_cstr(conn->id), octstr_get_cstr(type));
980  goto error;
981  }
982 
983  if (conndata->callbacks != NULL && conndata->callbacks->init != NULL && conndata->callbacks->init(conn, cfg)) {
984  error(0, "HTTP[%s]: submodule '%s' init failed.", octstr_get_cstr(conn->id), octstr_get_cstr(type));
985  goto error;
986  }
987 
988  conndata->open_sends = counter_create();
989  conndata->msg_to_send = gwlist_create();
990  gwlist_add_producer(conndata->msg_to_send);
991  conndata->http_ref = http_caller_create();
992 
993  conn->name = octstr_format("HTTP%s:%S:%d", (ssl?"S":""), type, conndata->port);
994 
995  if (conndata->send_url != NULL) {
996  conn->status = SMSCCONN_ACTIVE;
997  } else {
999  }
1000 
1001 
1002  conn->connect_time = time(NULL);
1003 
1004  conn->shutdown = httpsmsc_shutdown;
1005  conn->queued = httpsmsc_queued;
1006  conn->send_msg = httpsmsc_send;
1007 
1008  conndata->shutdown = 0;
1009 
1010  /* start receiver thread */
1011  if (conndata->port > 0) {
1012  if (http_open_port(conndata->port, ssl) == -1)
1013  goto error;
1014  if ((conndata->receive_thread = gwthread_create(httpsmsc_receiver, conn)) == -1)
1015  goto error;
1016  } else
1017  conndata->receive_thread = -1;
1018 
1019  /* start sender threads */
1020  if (conndata->send_url) {
1021  if ((conndata->send_cb_thread =
1022  gwthread_create(httpsmsc_send_cb, conn)) == -1)
1023  goto error;
1024  if ((conndata->sender_thread =
1025  gwthread_create(httpsmsc_sender, conn)) == -1)
1026  goto error;
1027  }
1028  else {
1029  conndata->send_cb_thread = conndata->sender_thread = -1;
1030  }
1031 
1032  info(0, "HTTP[%s]: Initiated and ready", octstr_get_cstr(conn->id));
1033 
1034  octstr_destroy(type);
1035  return 0;
1036 
1037 error:
1038  error(0, "HTTP[%s]: Failed to create HTTP SMSC connection",
1039  octstr_get_cstr(conn->id));
1040 
1041  if (conndata->callbacks != NULL && conndata->callbacks->destroy != NULL)
1042  conndata->callbacks->destroy(conn);
1043  conn->data = NULL;
1044  conndata_destroy(conndata);
1046  conn->status = SMSCCONN_DEAD;
1047  octstr_destroy(type);
1048  return -1;
1049 }
Octstr * name
Definition: smscconn_p.h:173
void error(int err, const char *fmt,...)
Definition: log.c:648
void info(int err, const char *fmt,...)
Definition: log.c:672
Octstr * dlr_url
Definition: smsc_http.c:152
void * data
Definition: smsc_http.c:171
static void httpsmsc_receiver(void *arg)
Definition: smsc_http.c:201
static void conndata_destroy(ConnData *conndata)
Definition: smsc_http.c:175
struct smsc_http_fn_callbacks smsc_http_xidris_callback
Definition: xidris.c:330
Octstr * alt_charset
Definition: smsc_http.c:162
long receive_thread
Definition: smsc_http.c:145
int ssl
int no_sep
Definition: smsc_http.c:160
Semaphore * semaphore_create(long n)
Definition: semaphore.c:81
Octstr * id
Definition: smscconn_p.h:174
void * data
Definition: smscconn_p.h:249
HTTPCaller * http_ref
Definition: smsc_http.c:144
struct smsc_http_fn_callbacks smsc_http_kannel_callback
Definition: smsc_http.c:801
int type
Definition: smsc_cimd2.c:215
Octstr * allow_ip
Definition: smsc_http.c:150
#define cfg_get(grp, varname)
Definition: cfg.h:86
struct smsc_http_fn_callbacks smsc_http_clickatell_callback
Definition: clickatell.c:308
Octstr * proxy
Definition: smsc_http.c:161
Octstr * system_id
Definition: smsc_http.c:157
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
void(* destroy)(SMSCConn *conn)
Definition: smsc_http.c:137
smscconn_killed_t why_killed
Definition: smscconn_p.h:153
struct smsc_http_fn_callbacks smsc_http_brunet_callback
Definition: brunet.c:317
volatile int shutdown
Definition: smsc_http.c:148
long port
Definition: smsc_http.c:149
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:281
Counter * open_sends
Definition: smsc_http.c:153
int no_coding
Definition: smsc_http.c:159
List * msg_to_send
Definition: smsc_http.c:163
Counter * counter_create(void)
Definition: counter.c:94
static void httpsmsc_send_cb(void *arg)
Definition: smsc_http.c:352
time_t connect_time
Definition: smscconn_p.h:155
struct smsc_http_fn_callbacks smsc_http_generic_callback
Definition: generic.c:609
int octstr_case_compare(const Octstr *os1, const Octstr *os2)
Definition: octstr.c:901
long sender_thread
Definition: smsc_http.c:147
void warning(int err, const char *fmt,...)
Definition: log.c:660
Octstr * octstr_format(const char *fmt,...)
Definition: octstr.c:2462
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
#define gwthread_create(func, arg)
Definition: gwthread.h:90
int no_sender
Definition: smsc_http.c:158
static int httpsmsc_shutdown(SMSCConn *conn, int finish_sending)
Definition: smsc_http.c:870
int http_open_port(int port, int ssl)
Definition: http.c:2499
Semaphore * max_pending_sends
Definition: smsc_http.c:154
int cfg_get_bool(int *n, CfgGroup *grp, Octstr *varname)
Definition: cfg.c:756
int(* init)(SMSCConn *conn, CfgGroup *cfg)
Definition: smsc_http.c:136
Definition: octstr.c:118
static long httpsmsc_queued(SMSCConn *conn)
Definition: smsc_http.c:859
int(* shutdown)(SMSCConn *conn, int finish_sending)
Definition: smscconn_p.h:229
Octstr * password
Definition: smsc_http.c:156
int cfg_get_integer(long *n, CfgGroup *grp, Octstr *varname)
Definition: cfg.c:739
#define panic
Definition: log.h:87
smscconn_status_t status
Definition: smscconn_p.h:151
HTTPCaller * http_caller_create(void)
Definition: http.c:897
#define gwlist_create()
Definition: list.h:136
long(* queued)(SMSCConn *conn)
Definition: smscconn_p.h:240
int(* send_msg)(SMSCConn *conn, Msg *msg)
Definition: smscconn_p.h:235
Octstr * username
Definition: smsc_http.c:155
static int httpsmsc_send(SMSCConn *conn, Msg *msg)
Definition: smsc_http.c:811
Octstr * send_url
Definition: smsc_http.c:151
void gwlist_add_producer(List *list)
Definition: list.c:383
static void httpsmsc_sender(void *arg)
Definition: smsc_http.c:282
struct smsc_http_fn_callbacks * callbacks
Definition: smsc_http.c:168
long send_cb_thread
Definition: smsc_http.c:146

Variable Documentation

◆ smsc_http_kannel_callback

struct smsc_http_fn_callbacks smsc_http_kannel_callback
Initial value:
= {
.send_sms = kannel_send_sms,
.parse_reply = kannel_parse_reply,
.receive_sms = kannel_receive_sms,
}
static void kannel_parse_reply(SMSCConn *conn, Msg *msg, int status, List *headers, Octstr *body)
Definition: smsc_http.c:599
static void kannel_receive_sms(SMSCConn *conn, HTTPClient *client, List *headers, Octstr *body, List *cgivars)
Definition: smsc_http.c:632
static int kannel_send_sms(SMSCConn *conn, Msg *sms)
Definition: smsc_http.c:496

Definition at line 801 of file smsc_http.c.

Referenced by smsc_http_create().

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