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

smsc.c

Go to the documentation of this file.
00001 /* ==================================================================== 
00002  * The Kannel Software License, Version 1.0 
00003  * 
00004  * Copyright (c) 2001-2008 Kannel Group  
00005  * Copyright (c) 1998-2001 WapIT Ltd.   
00006  * All rights reserved. 
00007  * 
00008  * Redistribution and use in source and binary forms, with or without 
00009  * modification, are permitted provided that the following conditions 
00010  * are met: 
00011  * 
00012  * 1. Redistributions of source code must retain the above copyright 
00013  *    notice, this list of conditions and the following disclaimer. 
00014  * 
00015  * 2. Redistributions in binary form must reproduce the above copyright 
00016  *    notice, this list of conditions and the following disclaimer in 
00017  *    the documentation and/or other materials provided with the 
00018  *    distribution. 
00019  * 
00020  * 3. The end-user documentation included with the redistribution, 
00021  *    if any, must include the following acknowledgment: 
00022  *       "This product includes software developed by the 
00023  *        Kannel Group (http://www.kannel.org/)." 
00024  *    Alternately, this acknowledgment may appear in the software itself, 
00025  *    if and wherever such third-party acknowledgments normally appear. 
00026  * 
00027  * 4. The names "Kannel" and "Kannel Group" must not be used to 
00028  *    endorse or promote products derived from this software without 
00029  *    prior written permission. For written permission, please  
00030  *    contact org@kannel.org. 
00031  * 
00032  * 5. Products derived from this software may not be called "Kannel", 
00033  *    nor may "Kannel" appear in their name, without prior written 
00034  *    permission of the Kannel Group. 
00035  * 
00036  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 
00037  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
00038  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
00039  * DISCLAIMED.  IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS 
00040  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,  
00041  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  
00042  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR  
00043  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
00044  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE  
00045  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,  
00046  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
00047  * ==================================================================== 
00048  * 
00049  * This software consists of voluntary contributions made by many 
00050  * individuals on behalf of the Kannel Group.  For more information on  
00051  * the Kannel Group, please see <http://www.kannel.org/>. 
00052  * 
00053  * Portions of this software are based upon software originally written at  
00054  * WapIT Ltd., Helsinki, Finland for the Kannel project.  
00055  */ 
00056 
00057 /*
00058  * smsc.c - implement interface to SMS centers as defined by smsc.h
00059  *
00060  * Lars Wirzenius and Kalle Marjola for WapIT Ltd.
00061  */
00062 
00063 /* NOTE: private functions (only for smsc_* use) are named smscenter_*,
00064  * public functions (used by gateway) are named smsc_*
00065  */
00066 
00067 #include <errno.h>
00068 #include <signal.h>
00069 #include <stdarg.h>
00070 #include <stdlib.h>
00071 #include <string.h>
00072 #include <time.h>
00073 #include <unistd.h>
00074 #include <sys/time.h>
00075 
00076 #include "gwlib/gwlib.h"
00077 #include "smsc.h"
00078 #include "smsc_p.h"
00079 #include "msg.h"
00080 
00081 /*
00082  * Maximum number of characters for read_into_buffer to read at a time.
00083  */
00084 #define MAX_READ_INTO_BUFFER    (1024)
00085 
00086 
00087 static void smscenter_lock(SMSCenter *smsc);
00088 static void smscenter_unlock(SMSCenter *smsc);
00089 
00090 /*--------------------------------------------------------------------
00091  * TODO: WAP WDP functions!
00092  */
00093 
00094 
00095 /*--------------------------------------------------------------------
00096  * smscenter functions
00097  */
00098 
00099 
00100 
00101 SMSCenter *smscenter_construct(void)
00102 {
00103     SMSCenter *smsc;
00104     static int next_id = 1;
00105 
00106     smsc = gw_malloc(sizeof(SMSCenter));
00107 
00108     smsc->killed = 0;
00109     smsc->type = SMSC_TYPE_DELETED;
00110     smsc->preferred_prefix = NULL;
00111     smsc->allowed_prefix = NULL;
00112     smsc->denied_prefix = NULL;
00113     smsc->alt_charset = 0;
00114     smsc->keepalive = 0;
00115 
00116     smsc->mutex = mutex_create();
00117 
00118     sprintf(smsc->name, "Unknown SMSC");
00119     smsc->id = next_id++;
00120 
00121     /* FAKE */
00122     smsc->hostname = NULL;
00123     smsc->port = -1;
00124     smsc->socket = -1;
00125 
00126     /* CIMD */
00127     smsc->cimd_hostname = NULL;
00128     smsc->cimd_port = -1;
00129     smsc->cimd_username = NULL;
00130     smsc->cimd_password = NULL;
00131 
00132     /* EMI_X25 */
00133     smsc->emi_phonenum = NULL;
00134     smsc->emi_serialdevice = NULL;
00135     smsc->emi_username = NULL;
00136     smsc->emi_password = NULL;
00137 
00138     /* SEMA SMS2000 */
00139     smsc->sema_smscnua = NULL;
00140     smsc->sema_homenua = NULL;
00141     smsc->sema_serialdevice = NULL;
00142     smsc->sema_fd = -1;
00143 
00144     /* SEMA SMS2000 OIS X.25 */
00145     smsc->ois_alive = 0;
00146     smsc->ois_alive2 = 0;
00147     smsc->ois_received_mo = NULL;
00148     smsc->ois_ack_debt = 0;
00149     smsc->ois_flags = 0;
00150     smsc->ois_listening_socket = -1;
00151     smsc->ois_socket = -1;
00152     smsc->ois_buflen = 0;
00153     smsc->ois_bufsize = 0;
00154     smsc->ois_buffer = 0;
00155 
00156     /* add new SMSCes here */
00157 
00158     /* Memory */
00159     smsc->buflen = 0;
00160     smsc->bufsize = 10*1024;
00161     smsc->buffer = gw_malloc(smsc->bufsize);
00162     memset(smsc->buffer, 0, smsc->bufsize);
00163 
00164     return smsc;
00165 }
00166 
00167 
00168 void smscenter_destruct(SMSCenter *smsc)
00169 {
00170     if (smsc == NULL)
00171         return;
00172 
00173     /* FAKE */
00174     gw_free(smsc->hostname);
00175 
00176     /* CIMD */
00177     gw_free(smsc->cimd_hostname);
00178     gw_free(smsc->cimd_username);
00179     gw_free(smsc->cimd_password);
00180 
00181     /* EMI_X25 */
00182     gw_free(smsc->emi_phonenum);
00183     gw_free(smsc->emi_serialdevice);
00184     gw_free(smsc->emi_username);
00185     gw_free(smsc->emi_password);
00186 
00187     /* SEMA */
00188     gw_free(smsc->sema_smscnua);
00189     gw_free(smsc->sema_homenua);
00190     gw_free(smsc->sema_serialdevice);
00191 
00192     /* OIS */
00193     ois_delete_queue(smsc);
00194     gw_free(smsc->ois_buffer);
00195 
00196     /* add new SMSCes here */
00197 
00198     /* Other fields */
00199     mutex_destroy(smsc->mutex);
00200 
00201     /* Memory */
00202     gw_free(smsc->buffer);
00203     gw_free(smsc);
00204 }
00205 
00206 
00207 
00208 
00209 int smscenter_submit_msg(SMSCenter *smsc, Msg *msg)
00210 {
00211     smscenter_lock(smsc);
00212 
00213     switch (smsc->type) {
00214 
00215     case SMSC_TYPE_CIMD:
00216         if (cimd_submit_msg(smsc, msg) == -1)
00217             goto error;
00218         break;
00219 
00220     case SMSC_TYPE_EMI_X25:
00221         if (emi_submit_msg(smsc, msg) == -1)
00222             goto error;
00223         break;
00224 
00225     case SMSC_TYPE_SEMA_X28:
00226         if (sema_submit_msg(smsc, msg) == -1)
00227             goto error;
00228         break;
00229 
00230     case SMSC_TYPE_OIS:
00231         if (ois_submit_msg(smsc, msg) == -1)
00232             goto error;
00233         break;
00234 
00235         /* add new SMSCes here */
00236 
00237     default:
00238         goto error;
00239     }
00240 
00241     smscenter_unlock(smsc);
00242     return 0;
00243 
00244 error:
00245     smscenter_unlock(smsc);
00246     return -1;
00247 }
00248 
00249 
00250 
00251 int smscenter_receive_msg(SMSCenter *smsc, Msg **msg)
00252 {
00253     int ret;
00254 
00255     smscenter_lock(smsc);
00256 
00257     switch (smsc->type) {
00258 
00259     case SMSC_TYPE_CIMD:
00260         ret = cimd_receive_msg(smsc, msg);
00261         if (ret == -1)
00262             goto error;
00263         break;
00264 
00265     case SMSC_TYPE_EMI_X25:
00266         ret = emi_receive_msg(smsc, msg);
00267         if (ret == -1)
00268             goto error;
00269         break;
00270 
00271     case SMSC_TYPE_OIS:
00272         ret = ois_receive_msg(smsc, msg);
00273         if (ret == -1)
00274             goto error;
00275         break;
00276 
00277 
00278     case SMSC_TYPE_SEMA_X28:
00279         ret = sema_receive_msg(smsc, msg);
00280         if (ret == -1)
00281             goto error;
00282         break;
00283 
00284     default:
00285         goto error;
00286 
00287     }
00288     smscenter_unlock(smsc);
00289 
00290     /* If the SMSC didn't set the timestamp, set it here. */
00291     if (ret == 1 && msg_type(*msg) == sms && (*msg)->sms.time == 0)
00292         time(&(*msg)->sms.time);
00293 
00294     return ret;
00295 
00296 error:
00297     smscenter_unlock(smsc);
00298     return -1;
00299 }
00300 
00301 
00302 int smscenter_pending_smsmessage(SMSCenter *smsc)
00303 {
00304     int ret;
00305 
00306     smscenter_lock(smsc);
00307 
00308     switch (smsc->type) {
00309 
00310     case SMSC_TYPE_CIMD:
00311         ret = cimd_pending_smsmessage(smsc);
00312         if (ret == -1)
00313             goto error;
00314         break;
00315 
00316     case SMSC_TYPE_EMI_X25:
00317         ret = emi_pending_smsmessage(smsc);
00318         if (ret == -1)
00319             goto error;
00320         break;
00321 
00322     case SMSC_TYPE_SEMA_X28:
00323         ret = sema_pending_smsmessage(smsc);
00324         if (ret == -1)
00325             goto error;
00326         break;
00327 
00328     case SMSC_TYPE_OIS:
00329         ret = ois_pending_smsmessage(smsc);
00330         if (ret == -1)
00331             goto error;
00332         break;
00333 
00334     default:
00335         goto error;
00336     }
00337 
00338     smscenter_unlock(smsc);
00339     return ret;
00340 
00341 error:
00342     error(0, "smscenter_pending_smsmessage is failing");
00343     smscenter_unlock(smsc);
00344     return -1;
00345 }
00346 
00347 
00348 int smscenter_read_into_buffer(SMSCenter *smsc)
00349 {
00350     char *p;
00351     int ret, result;
00352     fd_set read_fd;
00353     struct timeval tv, tvinit;
00354     size_t bytes_read;
00355 
00356     tvinit.tv_sec = 0;
00357     tvinit.tv_usec = 1000;
00358 
00359     bytes_read = 0;
00360     result = 0;
00361     for (;;) {
00362         FD_ZERO(&read_fd);
00363         FD_SET(smsc->socket, &read_fd);
00364         tv = tvinit;
00365         ret = select(smsc->socket + 1, &read_fd, NULL, NULL, &tv);
00366         if (ret == -1) {
00367             if (errno == EINTR) goto got_data;
00368             if (errno == EAGAIN) goto got_data;
00369             error(errno, "Error doing select for socket");
00370             goto error;
00371         } else if (ret == 0)
00372             goto got_data;
00373 
00374         if (smsc->buflen == smsc->bufsize) {
00375             p = gw_realloc(smsc->buffer, smsc->bufsize * 2);
00376             smsc->buffer = p;
00377             smsc->bufsize *= 2;
00378         }
00379 
00380         ret = read(smsc->socket,
00381                    smsc->buffer + smsc->buflen,
00382                    1);
00383         if (ret == -1) {
00384             error(errno, "Reading from `%s' port `%d' failed.",
00385                   smsc->hostname, smsc->port);
00386             goto error;
00387         }
00388         if (ret == 0)
00389             goto eof;
00390         smsc->buflen += ret;
00391         bytes_read += ret;
00392         if (bytes_read >= MAX_READ_INTO_BUFFER)
00393             break;
00394     }
00395 
00396 eof:
00397     ret = 0;
00398     goto unblock;
00399 
00400 got_data:
00401     ret = 1;
00402     goto unblock;
00403 
00404 error:
00405     ret = -1;
00406     goto unblock;
00407 
00408 unblock:
00409     return ret;
00410 }
00411 
00412 
00413 void smscenter_remove_from_buffer(SMSCenter *smsc, size_t n)
00414 {
00415     memmove(smsc->buffer, smsc->buffer + n, smsc->buflen - n);
00416     smsc->buflen -= n;
00417 }
00418 
00419 
00420 /*
00421  * Lock an SMSCenter. Return -1 for error, 0 for OK. 
00422  */
00423 static void smscenter_lock(SMSCenter *smsc)
00424 {
00425     if (smsc->type == SMSC_TYPE_DELETED)
00426         error(0, "smscenter_lock called on DELETED SMSC.");
00427     mutex_lock(smsc->mutex);
00428 }
00429 
00430 
00431 /*
00432  * Unlock an SMSCenter. Return -1 for error, 0 for OK.
00433  */
00434 static void smscenter_unlock(SMSCenter *smsc)
00435 {
00436     mutex_unlock(smsc->mutex);
00437 }
00438 
00439 
00440 /*------------------------------------------------------------------------
00441  * Public SMSC functions
00442  */
00443 
00444 
00445 SMSCenter *smsc_open(CfgGroup *grp)
00446 {
00447     SMSCenter *smsc;
00448     Octstr *type, *host, *username, *password, *phone, *device;
00449     Octstr *preferred_prefix, *allowed_prefix, *denied_prefix;
00450     Octstr *alt_chars, *allow_ip;
00451     Octstr *sema_smscnua, *sema_homenua, *sema_report;
00452     Octstr *sender_prefix;
00453 
00454     long iwaitreport;
00455     long port, receive_port, our_port;
00456     long keepalive;
00457     long ois_debug;
00458     long alt_dcs;
00459     int typeno;
00460 
00461 
00462     type = cfg_get(grp, octstr_imm("smsc"));
00463     if (type == NULL) {
00464     error(0, "Required field 'smsc' missing for smsc group.");
00465     return NULL;
00466     }
00467     if (octstr_compare(type, octstr_imm("cimd")) == 0)
00468         typeno = SMSC_TYPE_CIMD;
00469     else if (octstr_compare(type, octstr_imm("emi_x25")) == 0)
00470         typeno = SMSC_TYPE_EMI_X25;
00471     else if (octstr_compare(type, octstr_imm("sema")) == 0)
00472         typeno = SMSC_TYPE_SEMA_X28;
00473     else if (octstr_compare(type, octstr_imm("ois")) == 0)
00474         typeno = SMSC_TYPE_OIS;
00475     else {
00476     error(0, "Unknown SMSC type '%s'", octstr_get_cstr(type));
00477     octstr_destroy(type);
00478     return NULL;
00479     }
00480 
00481     host = cfg_get(grp, octstr_imm("host"));
00482     if (cfg_get_integer(&port, grp, octstr_imm("port")) == -1)
00483         port = 0;
00484     if (cfg_get_integer(&receive_port, grp, octstr_imm("receive-port")) == -1)
00485         receive_port = 0;
00486     if (cfg_get_integer(&our_port, grp, octstr_imm("our-port")) == -1)
00487         our_port = 0;
00488     username = cfg_get(grp, octstr_imm("smsc-username"));
00489     password = cfg_get(grp, octstr_imm("smsc-password"));
00490     phone = cfg_get(grp, octstr_imm("phone"));
00491     device = cfg_get(grp, octstr_imm("device"));
00492     preferred_prefix = cfg_get(grp, octstr_imm("preferred-prefix"));
00493     allowed_prefix = cfg_get(grp, octstr_imm("allowed-prefix"));
00494     denied_prefix = cfg_get(grp, octstr_imm("denied-prefix"));
00495     alt_chars = cfg_get(grp, octstr_imm("alt-charset"));
00496 
00497     allow_ip = cfg_get(grp, octstr_imm("connect-allow-ip"));
00498 
00499     sema_smscnua = cfg_get(grp, octstr_imm("smsc_nua"));
00500     sema_homenua = cfg_get(grp, octstr_imm("home_nua"));
00501     sema_report = cfg_get(grp, octstr_imm("wait_report"));
00502     if (sema_report == NULL)
00503         iwaitreport = 1;
00504     else
00505         octstr_parse_long(&iwaitreport, sema_report, 0, 0);
00506 
00507     if (cfg_get_integer(&keepalive, grp, octstr_imm("keepalive")) == -1)
00508         keepalive = 0;
00509 
00510     if (cfg_get_integer(&alt_dcs, grp, octstr_imm("alt-dcs")) == -1)
00511         alt_dcs = 0;
00512     if (alt_dcs > 1)
00513         alt_dcs = 1;
00514 
00515     if (cfg_get_integer(&ois_debug, grp, octstr_imm("ois-debug-level")) == -1)
00516         ois_debug = 0;
00517 
00518     sender_prefix = cfg_get(grp, octstr_imm("sender-prefix"));
00519     if (sender_prefix == NULL)
00520         sender_prefix = octstr_create("never");
00521 
00522     smsc = NULL;
00523 
00524     switch (typeno) {
00525     case SMSC_TYPE_CIMD:
00526         if (host == NULL || port == 0 || username == NULL || password == NULL)
00527             error(0, "Required field missing for CIMD center.");
00528         else
00529             smsc = cimd_open(octstr_get_cstr(host),
00530                          port, 
00531                          octstr_get_cstr(username), 
00532                  octstr_get_cstr(password));
00533         break;
00534 
00535     case SMSC_TYPE_EMI_X25:
00536         if (phone == NULL || device == NULL || username == NULL ||
00537             password == NULL)
00538             error(0, "Required field missing for EMI_X25 center.");
00539         else
00540             smsc = emi_open(octstr_get_cstr(phone), 
00541                         octstr_get_cstr(device), 
00542                 octstr_get_cstr(username), 
00543                 octstr_get_cstr(password));
00544         break;
00545 
00546     case SMSC_TYPE_SEMA_X28:
00547         if (device == NULL || sema_smscnua == NULL || sema_homenua == NULL)
00548             error(0, "Required field missing for SEMA center.");
00549         else
00550             smsc = sema_open(octstr_get_cstr(sema_smscnua), 
00551                          octstr_get_cstr(sema_homenua), 
00552                  octstr_get_cstr(device),
00553                              iwaitreport);
00554         break;
00555 
00556     case SMSC_TYPE_OIS:
00557         if (host == NULL || port == 0 || receive_port == 0)
00558             error(0, "Required field missing for OIS center.");
00559         else
00560             smsc = ois_open(receive_port, 
00561                         octstr_get_cstr(host), 
00562                 port, 
00563                         ois_debug);
00564         break;
00565 
00566         /* add new SMSCes here */
00567 
00568     default:        /* Unknown SMSC type */
00569         break;
00570     }
00571 
00572     if (smsc != NULL) {
00573     if (cfg_get_integer(&smsc->alt_charset, grp, 
00574                         octstr_imm("alt-charset")) == -1)
00575         smsc->alt_charset = 0;
00576         if (preferred_prefix == NULL)
00577         smsc->preferred_prefix = NULL;
00578     else
00579         smsc->preferred_prefix = 
00580             gw_strdup(octstr_get_cstr(preferred_prefix));
00581         if (allowed_prefix == NULL)
00582         smsc->allowed_prefix = NULL;
00583     else
00584         smsc->allowed_prefix = gw_strdup(octstr_get_cstr(allowed_prefix));
00585         if (denied_prefix == NULL)
00586         smsc->denied_prefix = NULL;
00587     else
00588         smsc->denied_prefix = gw_strdup(octstr_get_cstr(denied_prefix));
00589     }
00590 
00591     octstr_destroy(type);
00592     octstr_destroy(host);
00593     octstr_destroy(username);
00594     octstr_destroy(password);
00595     octstr_destroy(phone);
00596     octstr_destroy(device);
00597     octstr_destroy(preferred_prefix);
00598     octstr_destroy(denied_prefix);
00599     octstr_destroy(allowed_prefix);
00600     octstr_destroy(alt_chars);
00601     octstr_destroy(allow_ip);
00602     octstr_destroy(sema_smscnua);
00603     octstr_destroy(sema_homenua);
00604     octstr_destroy(sema_report);
00605     octstr_destroy(sender_prefix);
00606     return smsc;
00607 }
00608 
00609 
00610 
00611 int smsc_reopen(SMSCenter *smsc)
00612 {
00613     int ret;
00614 
00615     if (smsc->killed)
00616     return -2;
00617 
00618     smscenter_lock(smsc);
00619 
00620     switch (smsc->type) {
00621     case SMSC_TYPE_CIMD:
00622         ret = cimd_reopen(smsc);
00623     break;
00624     case SMSC_TYPE_EMI_X25:
00625         ret = emi_reopen(smsc);
00626     break;
00627     case SMSC_TYPE_SEMA_X28:
00628         ret = sema_reopen(smsc);
00629     break;
00630     case SMSC_TYPE_OIS:
00631         ret = ois_reopen(smsc);
00632     break;
00633         /* add new SMSCes here */
00634     default:        /* Unknown SMSC type */
00635         ret = -2;       /* no use */
00636     }
00637 
00638     smscenter_unlock(smsc);
00639     return ret;
00640 }
00641 
00642 
00643 
00644 char *smsc_name(SMSCenter *smsc)
00645 {
00646     return smsc->name;
00647 }
00648 
00649 int smsc_close(SMSCenter *smsc)
00650 {
00651     int errors = 0;
00652 
00653     if (smsc == NULL)
00654         return 0;
00655 
00656     smscenter_lock(smsc);
00657 
00658     switch (smsc->type) {
00659     case SMSC_TYPE_CIMD:
00660         if (cimd_close(smsc) == -1)
00661             errors = 1;
00662         break;
00663 
00664     case SMSC_TYPE_EMI_X25:
00665         if (emi_close(smsc) == -1)
00666             errors = 1;
00667         break;
00668 
00669     case SMSC_TYPE_SEMA_X28:
00670         if (sema_close(smsc) == -1)
00671             errors = 1;
00672         break;
00673 
00674     case SMSC_TYPE_OIS:
00675         if (ois_close(smsc) == -1)
00676             errors = 1;
00677         break;
00678 
00679         /* add new SMSCes here */
00680 
00681     default:        /* Unknown SMSC type */
00682         break;
00683     }
00684     /*
00685      smsc->type = SMSC_TYPE_DELETED;
00686      smscenter_unlock(smsc);
00687     */
00688     if (errors)
00689         return -1;
00690 
00691     return 0;
00692 }
00693 
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.