Hi Stipe. Wow..this sounds really usefull.. I can already use it, but I think we should have it as a separate patch for now, the CVS is relatively stable, and this is quite a big internal change. I would be happy to try it on our dev servers.
nisan At 09:58 PM 9/6/02 +0200, Stipe Tolj wrote: >Hi all, > >attached is a patch that I developed today for internal smsbox routing >inside bearerbox. The patch is quite big, so I'll try to explain what >the intention is and what it does. > >Basically currently any sms that arrives at bearerbox via a specific >thread of a specific smsc module is produced to a global queue >(incoming_sms). All connected smsbox'es do grap a msg from that queue >all process it. This mechanism is basically used to load-balance msg >traffic to various smsbox'es. > >However, sometimes it may be desireable for various reasons to be able >to "route" the sms msg to a specific smsbox. This has to be done >inside bearerbox, between the smsc module layer and the communication >to the smsbox'es. > >First, bearerbox needs to know about smsboxes in a way that is >semantically more relevant. We know the IP of the smsbox and even a >local file descriptor, but that's not enough. Imagine a smsbox sending >a DLR-requesting msg. Not smsbox(1) sends msg to bearerbox, bearerbox >holds the dlr queue, receives the report from the smsc module and now >does not know if it should route to smsbox(1) or smsbox(2). Now >basically in this easy scenario it does not matter, because each >smsbox instance does "only" a URL lookup. But think of a SMPP proxying >box that has own state tables and reports have to be re-routed exactly >to that instance to update status tables. > >Ok, here is how the thing works: > > * gw/smsbox.c: graps a 'smsbox-id' from it's config group and sends >an admin msg identifying itself with a id to bearerbox > * gw/bb_boxc.c: when an admin msg is received by an identicying >smsbox, the incoming queue is switched to a private list, so that no >other smsbox shares the same list with the new identified smsbox > * gw/msg.h: adding a boxc_id Octstr to type sms to hold the >smsbox-id while transporting msg from smsbox'es to bearerbox > * gw/dlr.c: adding a boxc_id parameter to the dlr_add() abstraction >layers and to the relecant smsc_foobar.c modules > * the message went out of the smsc module door > * the delivery report comes in > * gw/dlr.c: dlr_find() inserts the remembered boxc_id to the msg >structure and passes it through the smsc module to gw/bb_smscconn.c > * gw/bb_smscconn.c: gets all incoming sms from the smsc modules and >calls the new gw/bb_boxc.c:route_incoming_sms() routine to descride to >while list this msg is produced and hence to which smsbox the msg is >routed > >The smsbox routing is defined in the configuration file via the >multi-grou "smsbox-route", like this > > group = smsbox-route > smsbox-id = smsbox_1 > smsc_ids = "fake_1;fake_2;fake_3" > shortcuts = "83444;83555" > >which means route any message coming from the smsc-id's or >msg.receiver number to this smsbox instance. > >To store the mapping and routing information, 3 hash dictionaries are >used. One that holds all connection pointers from the smsbox'es and 2 >seperate dictionaries for the smsc-id and receiver number mapping. > >I'd like to apply the patch. Mainly it does not change any current >behaviour, but it's still a cerious change in the bearerbox internals, >so I'd like to ask for comments or objections before going to commit >this. I have tested a lot of this, but no garantee, as always :)) > >Stipe > >[EMAIL PROTECTED] >------------------------------------------------------------------- >Wapme Systems AG > >Vogelsanger Weg 80 >40470 Düsseldorf > >Tel: +49-211-74845-0 >Fax: +49-211-74845-299 > >E-Mail: [EMAIL PROTECTED] >Internet: http://www.wapme-systems.de >------------------------------------------------------------------- >wapme.net - wherever you arediff -ru gateway/gw/bb_boxc.c >gateway-smpp/gw/bb_boxc.c >--- gateway/gw/bb_boxc.c 2002-09-06 14:03:16.000000000 +0200 >+++ gateway-smpp/gw/bb_boxc.c 2002-09-06 21:21:16.000000000 +0200 >@@ -40,6 +40,9 @@ > static volatile sig_atomic_t wapbox_running; > static List *wapbox_list = NULL; > static List *smsbox_list = NULL; >+static Dict *smsbox_by_id = NULL; >+static Dict *smsbox_by_smsc = NULL; >+static Dict *smsbox_by_receiver = NULL; > > static long smsbox_port; > static int smsbox_port_ssl = 0; >@@ -65,6 +68,7 @@ > List *retry; /* If sending fails */ > List *outgoing; > volatile sig_atomic_t alive; >+ Octstr *boxc_id; > } Boxc; > > >@@ -173,6 +177,26 @@ > store_save(msg); > debug("bb.boxc", 0, "boxc_receiver: got ack"); > } >+ else if (msg_type(msg) == admin && msg->admin.command == >cmd_identify) { >+ List *newlist; >+ >+ /* and add the boxc_ud into conn for boxc_status() output */ >+ if (conn->boxc_id == NULL) >+ conn->boxc_id = octstr_duplicate(msg->admin.boxc_id); >+ /* >+ * re-link the incoming queue for this connection to an >independent >+ */ >+ newlist = list_create(); >+ list_add_producer(newlist); >+ conn->incoming = newlist; >+ conn->retry = newlist; >+ >+ /* add this identified smsbox to the dictionary */ >+ dict_put(smsbox_by_id, msg->admin.boxc_id, conn); >+ debug("bb.boxc", 0, "boxc_receiver: got boxc_id <%s> >from <%s>", >+ octstr_get_cstr(msg->admin.boxc_id), >+ octstr_get_cstr(conn->client_ip)); >+ } > else > warning(0, "boxc_receiver: unknown msg received > from <%s>, " > "ignored", octstr_get_cstr(conn->client_ip)); >@@ -270,6 +294,7 @@ > boxc->client_ip = ip; > boxc->alive = 1; > boxc->connect_time = time(NULL); >+ boxc->boxc_id = NULL; > return boxc; > } > >@@ -283,6 +308,8 @@ > if (boxc->conn) > conn_destroy(boxc->conn); > octstr_destroy(boxc->client_ip); >+ if (boxc->boxc_id) >+ octstr_destroy(boxc->boxc_id); > gw_free(boxc); > } > >@@ -349,6 +376,7 @@ > list_remove_producer(flow_threads); > return; > } >+ > newconn->incoming = incoming_sms; > newconn->retry = incoming_sms; > newconn->outgoing = outgoing_sms; >@@ -367,7 +395,14 @@ > > gwthread_join(sender); > >-cleanup: >+cleanup: >+ if (newconn->boxc_id) { >+ dict_remove(smsbox_by_id, newconn->boxc_id); >+ while (list_producer_count(newconn->incoming) > 0) >+ list_remove_producer(newconn->incoming); >+ gw_assert(list_len(newconn->incoming) == 0); >+ list_destroy(newconn->incoming, NULL); >+ } > list_delete_equal(smsbox_list, newconn); > boxc_destroy(newconn); > >@@ -676,6 +711,12 @@ > > list_destroy(smsbox_list, NULL); > smsbox_list = NULL; >+ dict_destroy(smsbox_by_id); >+ smsbox_by_id = NULL; >+ dict_destroy(smsbox_by_smsc); >+ smsbox_by_smsc = NULL; >+ dict_destroy(smsbox_by_receiver); >+ smsbox_by_receiver = NULL; > > list_remove_producer(flow_threads); > } >@@ -721,6 +762,60 @@ > } > > >+/* >+ * Populates the corresponding smsbox_by_foobar dictionary hash tables >+ */ >+static void init_smsbox_routes(Cfg *cfg) >+{ >+ CfgGroup *grp; >+ List *list, *items; >+ Octstr *boxc_id, *smsc_ids, *shortcuts; >+ int i; >+ >+ boxc_id = smsc_ids = shortcuts = NULL; >+ >+ list = cfg_get_multi_group(cfg, octstr_imm("smsbox-route")); >+ >+ /* loop multi-group "smsbox-route" */ >+ while (list && (grp = list_extract_first(list)) != NULL) { >+ >+ if ((boxc_id = cfg_get(grp, octstr_imm("smsbox-id"))) == NULL) { >+ grp_dump(grp); >+ panic(0,"'smsbox-route' group without valid 'smsbox-id' >directive!"); >+ } >+ smsc_ids = cfg_get(grp, octstr_imm("smsc-ids")); >+ shortcuts = cfg_get(grp, octstr_imm("shortcuts")); >+ >+ /* now parse the smsc-ids and shortcuts semicolon seperated list */ >+ if (smsc_ids) { >+ items = octstr_split(smsc_ids, octstr_imm(";")); >+ for (i = 0; i < list_len(items); i++) { >+ Octstr *item = list_get(items, i); >+ >+ debug("bb.boxc",0,"Adding smsbox routing to id <%s> for >smsc id <%s>", >+ octstr_get_cstr(boxc_id), octstr_get_cstr(item)); >+ >+ dict_put(smsbox_by_smsc, item, boxc_id); >+ } >+ list_destroy(items, octstr_destroy_item); >+ } >+ >+ if (shortcuts) { >+ items = octstr_split(shortcuts, octstr_imm(";")); >+ for (i = 0; i < list_len(items); i++) { >+ Octstr *item = item = list_get(items, i); >+ >+ debug("bb.boxc",0,"Adding smsbox routing to id <%s> for >receiver no <%s>", >+ octstr_get_cstr(boxc_id), octstr_get_cstr(item)); >+ >+ dict_put(smsbox_by_receiver, item, boxc_id); >+ } >+ list_destroy(items, octstr_destroy_item); >+ } >+ } >+} >+ >+ > > /*------------------------------------------------------------- > * public functions >@@ -750,6 +845,12 @@ > > > smsbox_list = list_create(); /* have a list of connections */ >+ smsbox_by_id = dict_create(10, NULL); /* and a hash directory of >identified */ >+ smsbox_by_smsc = dict_create(30, (void(*)(void *)) octstr_destroy); >+ smsbox_by_receiver = dict_create(50, (void(*)(void *)) octstr_destroy); >+ >+ init_smsbox_routes(cfg); >+ > list_add_producer(outgoing_sms); > > smsbox_running = 1; >@@ -907,8 +1008,9 @@ > #endif > ); > else >- octstr_format_append(tmp, "%ssmsbox, IP %s (on-line >%ldd %ldh %ldm %lds) %s %s", >- ws, octstr_get_cstr(bi->client_ip), >+ octstr_format_append(tmp, "%ssmsbox:%s, IP %s (on-line >%ldd %ldh %ldm %lds) %s %s", >+ ws, (bi->boxc_id ? >octstr_get_cstr(bi->boxc_id) : "(none)"), >+ octstr_get_cstr(bi->client_ip), > t/3600/24, t/3600%24, t/60%60, t%60, > #ifdef HAVE_LIBSSL > conn_get_ssl(bi->conn) != NULL ? "using SSL" : "", >@@ -958,3 +1060,59 @@ > box_allow_ip = NULL; > box_deny_ip = NULL; > } >+ >+/* >+ * Route the incoming message to a specific smsbox conn >+ * or simply to a random if no shortcut routing and msg->sms.boxc_id >+ * match. >+ */ >+void route_incoming_sms(Msg *msg) >+{ >+ Boxc *conn = NULL; >+ Octstr *s, *r; >+ >+ s = r = NULL; >+ gw_assert(msg_type(msg) == sms); >+ >+ msg_dump(msg, 0); >+ >+ /* >+ * We have a specific route to pass this msg to smsbox-id >+ * Lookup the connection in the dictionary. >+ */ >+ if (msg->sms.boxc_id != NULL) { >+ >+ conn = dict_get(smsbox_by_id, msg->sms.boxc_id); >+ if (conn == 0) { >+ /* >+ * something is wrong, this was the smsbox connection we used >+ * for sending, so it seems this smsbox is gone >+ */ >+ error(0,"Could not route message to smsbox id <%s>, smsbox is >gone!", >+ octstr_get_cstr(msg->sms.boxc_id)); >+ } >+ } >+ >+ /* >+ * Check if we have a "smsbox-route" for this msg. >+ * Where the shortcut route has a higher priority then the smsc-id rule. >+ */ >+ if (conn == NULL) { >+ s = (msg->sms.smsc_id ? dict_get(smsbox_by_smsc, >msg->sms.smsc_id) : NULL); >+ r = (msg->sms.receiver ? dict_get(smsbox_by_receiver, >msg->sms.receiver) : NULL); >+ conn = r ? dict_get(smsbox_by_id, r) : (s ? >dict_get(smsbox_by_id, s) : NULL); >+ } >+ >+ /* >+ * ok, none of the routing things applied previously, so route it to >+ * a random smsbox via the shared incoming_sms queue, otherwise to the >+ * smsc specific incoming queue >+ */ >+ if (conn == NULL) >+ list_produce(incoming_sms, msg); >+ else >+ list_produce(conn->incoming, msg); >+ >+} >+ >+ >diff -ru gateway/gw/bb_smscconn.c gateway-smpp/gw/bb_smscconn.c >--- gateway/gw/bb_smscconn.c 2002-09-06 14:03:16.000000000 +0200 >+++ gateway-smpp/gw/bb_smscconn.c 2002-09-06 18:30:47.000000000 +0200 >@@ -44,6 +44,7 @@ > extern List *flow_threads; > extern List *suspended; > extern List *isolated; >+extern Dict *smsbox_routes; > > /* our own thingies */ > >@@ -59,6 +60,8 @@ > > static long router_thread = -1; > >+void route_incoming_sms(Msg *sms); >+ > static void log_sms(SMSCConn *conn, Msg *sms, char *message) > { > Octstr *text, *udh; >@@ -233,7 +236,14 @@ > else > log_sms(conn, sms, "DLR SMS"); > >- list_produce(incoming_sms, sms); >+ /* >+ * Now try to route the message to a specific smsbox >+ * connection based on the existing msg->sms.boxc_id or >+ * the registered receiver numbers for specific smsbox'es. >+ */ >+ route_incoming_sms(sms); >+ >+ //list_produce(incoming_sms, sms); > counter_increase(incoming_sms_counter); > counter_increase(conn->received); > >diff -ru gateway/gw/dlr.c gateway-smpp/gw/dlr.c >--- gateway/gw/dlr.c 2002-09-06 14:03:16.000000000 +0200 >+++ gateway-smpp/gw/dlr.c 2002-09-06 15:22:41.000000000 +0200 >@@ -13,6 +13,11 @@ > * added more abstraction to fit for several other storage types > * 2002-08-04: [EMAIL PROTECTED]: > * added simple database library (sdb) support >+ * 2002-09-06: [EMAIL PROTECTED]: >+ * added re-routing info for DLRs to route via bearerbox to the same >smsbox >+ * instance. This is required if you use state conditioned smsboxes >or smppboxes >+ * via one bearerbox. Previously bearerbox was simple ignoring to >which smsbox >+ * connection a msg is passed. Now we can route the messages inside >bearerbox. > */ > > #include <ctype.h> >@@ -44,6 +49,7 @@ > Octstr *service; > Octstr *url; > int mask; >+ Octstr *boxc_id; > } dlr_wle; > > /* >@@ -103,6 +109,8 @@ > panic(0, "DLR: DB: directive 'field-mask' is not specified!"); > if (!(field_status = cfg_get(grp, octstr_imm("field-status")))) > panic(0, "DLR: DB: directive 'field-status' is not specified!"); >+ if (!(field_boxc = cfg_get(grp, octstr_imm("field-boxc-id")))) >+ panic(0, "DLR: DB: directive 'field-boxc-id' is not specified!"); > } > #endif > >@@ -376,6 +384,7 @@ > O_DELETE (dlr->destination); > O_DELETE (dlr->service); > O_DELETE (dlr->url); >+ O_DELETE (dlr->boxc_id); > dlr->mask = 0; > gw_free(dlr); > } >@@ -386,15 +395,15 @@ > */ > > static void dlr_add_mem(char *smsc, char *ts, char *src, char *dst, >- char *service, char *url, int mask) >+ char *service, char *url, int mask, char *boxc) > { > dlr_wle *dlr; > > if (mask & 0x1F) { > dlr = dlr_new(); > >- debug("dlr.dlr", 0, "Adding DLR smsc=%s, ts=%s, src=%s, dst=%s, >mask=%d", >- smsc, ts, src, dst, mask); >+ debug("dlr.dlr", 0, "Adding DLR smsc=%s, ts=%s, src=%s, dst=%s, >mask=%d, boxc=%s", >+ smsc, ts, src, dst, mask, boxc); > > dlr->smsc = octstr_create(smsc); > dlr->timestamp = octstr_create(ts); >@@ -402,26 +411,28 @@ > dlr->destination = octstr_create(dst); > dlr->service = octstr_create(service); > dlr->url = octstr_create(url); >+ dlr->boxc_id = octstr_create(boxc); > dlr->mask = mask; > list_append(dlr_waiting_list,dlr); > } > } > > static void dlr_add_mysql(char *smsc, char *ts, char *src, char *dst, >- char *service, char *url, int mask) >+ char *service, char *url, int mask, char *boxc) > { > #ifdef DLR_MYSQL > Octstr *sql; > int state; > >- sql = octstr_format("INSERT INTO %s (%s, %s, %s, %s, %s, %s, %s, %s) >VALUES " >- "('%s', '%s', '%s', '%s', '%s', '%s', '%d', '%d');", >+ sql = octstr_format("INSERT INTO %s (%s, %s, %s, %s, %s, %s, %s, %s, >%s) VALUES " >+ "('%s', '%s', '%s', '%s', '%s', '%s', '%d', '%s', >'%d');", > octstr_get_cstr(table), > octstr_get_cstr(field_smsc), > octstr_get_cstr(field_ts), > octstr_get_cstr(field_src), > octstr_get_cstr(field_dst), > octstr_get_cstr(field_serv), > octstr_get_cstr(field_url), >- octstr_get_cstr(field_mask), >octstr_get_cstr(field_status), >- smsc, ts, src, dst, service, url, mask, 0); >+ octstr_get_cstr(field_mask), >octstr_get_cstr(field_boxc), >+ octstr_get_cstr(field_status), >+ smsc, ts, src, dst, service, url, mask, boxc, 0); > > mutex_lock(dlr_mutex); > >@@ -435,20 +446,21 @@ > } > > static void dlr_add_sdb(char *smsc, char *ts, char *src, char *dst, >- char *service, char *url, int mask) >+ char *service, char *url, int mask, char *boxc) > { > #ifdef DLR_SDB > Octstr *sql; > int state; > >- sql = octstr_format("INSERT INTO %s (%s, %s, %s, %s, %s, %s, %s, %s) >VALUES " >- "('%s', '%s', '%s', '%s', '%s', '%s', '%d', '%d')", >+ sql = octstr_format("INSERT INTO %s (%s, %s, %s, %s, %s, %s, %s, %s, >%s) VALUES " >+ "('%s', '%s', '%s', '%s', '%s', '%s', '%d', '%s', >'%d')", > octstr_get_cstr(table), > octstr_get_cstr(field_smsc), > octstr_get_cstr(field_ts), > octstr_get_cstr(field_src), > octstr_get_cstr(field_dst), > octstr_get_cstr(field_serv), > octstr_get_cstr(field_url), >- octstr_get_cstr(field_mask), >octstr_get_cstr(field_status), >- smsc, ts, src, dst, service, url, mask, 0); >+ octstr_get_cstr(field_mask), >octstr_get_cstr(field_boxc), >+ octstr_get_cstr(field_status), >+ smsc, ts, src, dst, service, url, mask, boxc, 0); > > mutex_lock(dlr_mutex); > >@@ -462,16 +474,16 @@ > } > > void dlr_add(char *smsc, char *ts, char *src, char *dst, >- char *keyword, char *id, int mask) >+ char *keyword, char *id, int mask, char *boxc) > { > if (octstr_compare(dlr_type, octstr_imm("internal")) == 0) { >- dlr_add_mem(smsc, ts, src, dst, keyword, id, mask); >+ dlr_add_mem(smsc, ts, src, dst, keyword, id, mask, boxc); > } else > if (octstr_compare(dlr_type, octstr_imm("mysql")) == 0) { >- dlr_add_mysql(smsc, ts, src, dst, keyword, id, mask); >+ dlr_add_mysql(smsc, ts, src, dst, keyword, id, mask, boxc); > } else > if (octstr_compare(dlr_type, octstr_imm("sdb")) == 0) { >- dlr_add_sdb(smsc, ts, src, dst, keyword, id, mask); >+ dlr_add_sdb(smsc, ts, src, dst, keyword, id, mask, boxc); > > /* > * add aditional types here >@@ -522,6 +534,13 @@ > */ > msg->sms.msgdata = NULL; > >+ /* >+ * If a boxc_id is available, then instruct bearerbox to >+ * route this msg back to originating smsbox >+ */ >+ msg->sms.boxc_id = octstr_len(dlr->boxc_id) ? >+ octstr_duplicate(dlr->boxc_id) : NULL; >+ > time(&msg->sms.time); > debug("dlr.dlr", 0, "created DLR message for URL <%s>", > octstr_get_cstr(msg->sms.dlr_url)); >@@ -555,12 +574,14 @@ > Octstr *dlr_service; > Octstr *dlr_url; > Octstr *source_addr; >+ Octstr *boxc_id; > MYSQL_RES *result; > MYSQL_ROW row; > >- sql = octstr_format("SELECT %s, %s, %s, %s FROM %s WHERE %s='%s' AND >%s='%s';", >+ sql = octstr_format("SELECT %s, %s, %s, %s, %s FROM %s WHERE %s='%s' >AND %s='%s';", > octstr_get_cstr(field_mask), > octstr_get_cstr(field_serv), > octstr_get_cstr(field_url), > octstr_get_cstr(field_src), >+ octstr_get_cstr(field_boxc), > octstr_get_cstr(table), octstr_get_cstr(field_smsc), > smsc, octstr_get_cstr(field_ts), ts); > >@@ -588,15 +609,13 @@ > return NULL; > } > >- debug("dlr.mysql", 0, "Found entry, row[0]=%s, row[1]=%s, row[2]=%s, >row[3]=%s", >- row[0], row[1], row[2], row[3] ? row[3] : "NULL"); >+ debug("dlr.mysql", 0, "Found entry, row[0]=%s, row[1]=%s, row[2]=%s, >row[3]=%s, row[4]=%s", >+ row[0], row[1], row[2], (row[3] ? row[3] : "NULL"), (row[4] ? >row[4] : "NULL")); > dlr_mask = atoi(row[0]); > dlr_service = octstr_create(row[1]); > dlr_url = octstr_create(row[2]); >- if(row[3]) >- source_addr = octstr_create(row[3]); >- else >- source_addr = octstr_create(""); >+ source_addr = row[3] ? octstr_create(row[3]) : octstr_create(""); >+ boxc_id = row[4] ? octstr_create(row[4]) : octstr_create(""); > mysql_free_result(result); > > mutex_unlock(dlr_mutex); >@@ -630,7 +649,7 @@ > > /* if dlr_url was present, recode it here again */ > msg->sms.dlr_url = octstr_len(dlr_url) ? >- octstr_duplicate(dlr_url) : NULL; >+ octstr_duplicate(dlr_url) : NULL; > > /* > * insert orginal message to the data segment >@@ -638,6 +657,13 @@ > */ > msg->sms.msgdata = NULL; > >+ /* >+ * If a boxc_id is available, then instruct bearerbox to >+ * route this msg back to originating smsbox >+ */ >+ msg->sms.boxc_id = octstr_len(boxc_id) ? >+ octstr_duplicate(boxc_id) : NULL; >+ > time(&msg->sms.time); > debug("dlr.dlr", 0, "created DLR message for URL <%s>", > octstr_get_cstr(msg->sms.dlr_url)); >@@ -667,6 +693,7 @@ > octstr_destroy(dlr_service); > octstr_destroy(dlr_url); > octstr_destroy(source_addr); >+ octstr_destroy(boxc_id); > > #endif > return msg; >@@ -682,7 +709,7 @@ > > /* strip string into words */ > row = octstr_split(octstr_imm(p[0]), octstr_imm(" ")); >- if (list_len(row) != 4) { >+ if (list_len(row) != 5) { > debug("dlr.sdb", 0, "Row has wrong length %ld", list_len(row)); > return 0; > } >@@ -704,11 +731,13 @@ > Octstr *dlr_service; > Octstr *dlr_url; > Octstr *source_addr; >+ Octstr *boxc_id; > List *row; > >- sql = octstr_format("SELECT %s, %s, %s, %s FROM %s WHERE %s='%s' AND >%s='%s'", >+ sql = octstr_format("SELECT %s, %s, %s, %s, %s FROM %s WHERE %s='%s' >AND %s='%s'", > octstr_get_cstr(field_mask), > octstr_get_cstr(field_serv), >- octstr_get_cstr(field_url), >octstr_get_cstr(field_src), >+ octstr_get_cstr(field_url), >octstr_get_cstr(field_src), >+ octstr_get_cstr(field_boxc), > octstr_get_cstr(table), octstr_get_cstr(field_smsc), > smsc, octstr_get_cstr(field_ts), ts); > >@@ -722,16 +751,18 @@ > return NULL; > } > >- debug("dlr.sdb", 0, "Found entry, row[0]=%s, row[1]=%s, row[2]=%s, >row[3]=%s", >+ debug("dlr.sdb", 0, "Found entry, row[0]=%s, row[1]=%s, row[2]=%s, >row[3]=%s row[4]=%s", > octstr_get_cstr(list_get(row, 0)), > octstr_get_cstr(list_get(row, 1)), > octstr_get_cstr(list_get(row, 2)), >- octstr_get_cstr(list_get(row, 3))); >+ octstr_get_cstr(list_get(row, 3)) >+ octstr_get_cstr(list_get(row, 4))); > > dlr_mask = atoi(octstr_get_cstr(list_get(row, 0))); > dlr_service = octstr_duplicate(list_get(row, 1)); > dlr_url = octstr_duplicate(list_get(row, 2)); > source_addr = octstr_duplicate(list_get(row, 3)); >+ boxc_id = octstr_duplicate(list_get(row, 4)); > list_destroy(row, octstr_destroy_item); > > mutex_unlock(dlr_mutex); >@@ -773,6 +804,13 @@ > */ > msg->sms.msgdata = NULL; > >+ /* >+ * If a boxc_id is available, then instruct bearerbox to >+ * route this msg back to originating smsbox >+ */ >+ msg->sms.boxc_id = octstr_len(boxc_id) ? >+ octstr_duplicate(boxc_id) : NULL; >+ > time(&msg->sms.time); > debug("dlr.dlr", 0, "created DLR message for URL <%s>", > octstr_get_cstr(msg->sms.dlr_url)); >@@ -802,6 +840,7 @@ > octstr_destroy(dlr_service); > octstr_destroy(dlr_url); > octstr_destroy(source_addr); >+ octstr_destroy(boxc_id); > > #endif > return msg; >diff -ru gateway/gw/dlr.h gateway-smpp/gw/dlr.h >--- gateway/gw/dlr.h 2002-09-04 19:06:12.000000000 +0200 >+++ gateway-smpp/gw/dlr.h 2002-09-06 15:04:45.000000000 +0200 >@@ -38,7 +38,7 @@ > #endif > Octstr *table; > Octstr *field_smsc, *field_ts, *field_src, *field_dst, *field_serv; >-Octstr *field_url, *field_mask, *field_status; >+Octstr *field_url, *field_mask, *field_status, *field_boxc; > #endif > > /* macros */ >@@ -54,7 +54,7 @@ > * Add a new entry to the list > */ > void dlr_add(char *smsc, char *ts, char *src, char *dst, >- char *keyword, char *id, int mask); >+ char *keyword, char *id, int mask, char *boxc); > > /* > * Find an entry in the list. If there is one a message is returned and >diff -ru gateway/gw/msg-decl.h gateway-smpp/gw/msg-decl.h >--- gateway/gw/msg-decl.h 2002-08-05 16:02:23.000000000 +0200 >+++ gateway-smpp/gw/msg-decl.h 2002-09-06 16:26:17.000000000 +0200 >@@ -16,9 +16,10 @@ > }) > > MSG(admin, >- { >- INTEGER(command); >- }) >+ { >+ INTEGER(command); >+ OCTSTR(boxc_id); >+ }) > > MSG(sms, > { >@@ -42,8 +43,9 @@ > OCTSTR(dlr_url); > INTEGER(pid); > INTEGER(alt_dcs); >- INTEGER(rpi); >+ INTEGER(rpi); > OCTSTR(charset); >+ OCTSTR(boxc_id); > }) > > MSG(ack, >@@ -62,6 +64,7 @@ > OCTSTR(user_data); > }) > >+ > #undef MSG > #undef INTEGER > #undef OCTSTR >diff -ru gateway/gw/msg.h gateway-smpp/gw/msg.h >--- gateway/gw/msg.h 2001-10-11 19:18:33.000000000 +0200 >+++ gateway-smpp/gw/msg.h 2002-09-06 16:27:24.000000000 +0200 >@@ -43,7 +43,8 @@ > enum { > cmd_shutdown = 0, > cmd_suspend = 1, >- cmd_resume = 2 >+ cmd_resume = 2, >+ cmd_identify = 3 > }; > > /* >diff -ru gateway/gw/smsbox.c gateway-smpp/gw/smsbox.c >--- gateway/gw/smsbox.c 2002-08-19 19:25:59.000000000 +0200 >+++ gateway-smpp/gw/smsbox.c 2002-09-06 16:56:28.000000000 +0200 >@@ -44,6 +44,7 @@ > static long bb_port; > static int bb_ssl = 0; > static long sendsms_port = 0; >+static Octstr *smsbox_id = NULL; > static Octstr *sendsms_url = NULL; > static Octstr *sendota_url = NULL; > static Octstr *xmlrpc_url = NULL; >@@ -75,6 +76,22 @@ > * Communication with the bearerbox. > */ > >+/* >+ * If we have a smsbox-id set, identify to bearerbox for smsbox-specific >+ * routing inside bearerbox. >+ */ >+static void identify_to_bearerbox(void) >+{ >+ Msg *msg; >+ >+ if (smsbox_id != NULL) { >+ msg = msg_create(admin); >+ msg->admin.command = cmd_identify; >+ msg->admin.boxc_id = octstr_duplicate(smsbox_id); >+ write_to_bearerbox(msg); >+ } >+} >+ > > /* > * Read an Msg from the bearerbox and send it to the proper receiver >@@ -156,6 +173,15 @@ > info(0, "No reply sent, denied."); > return 0; > } >+ >+ /* >+ * Encode our smsbox-id to the msg structure. >+ * This will allow bearerbox to return specific answers to the >+ * same smsbox, mainly for DLRs and SMS proxy modes. >+ */ >+ if (smsbox_id != NULL) { >+ msg->sms.boxc_id = octstr_duplicate(smsbox_id); >+ } > > /* Empty message? Either ignore it or substitute the "empty" > * warning defined */ >@@ -1444,7 +1470,6 @@ > reply_msg->ack.time = msg->sms.time; > reply_msg->ack.id = msg->sms.id; > >- > if (dreport) { > trans = urltrans_find_service(translations, msg); > >@@ -2861,6 +2886,8 @@ > if (grp == NULL) > panic(0, "No 'smsbox' group in configuration"); > >+ smsbox_id = cfg_get(grp, octstr_imm("smsbox-id")); >+ > p = cfg_get(grp, octstr_imm("bearerbox-host")); > if (p != NULL) { > octstr_destroy(bb_host); >@@ -3047,6 +3074,7 @@ > info(0, GW_NAME "Could not start heartbeat."); > } > >+ identify_to_bearerbox(); > read_messages_from_bearerbox(); > > info(0, GW_NAME " smsbox terminating."); >@@ -3074,6 +3102,7 @@ > octstr_destroy(bb_host); > octstr_destroy(global_sender); > octstr_destroy(accepted_chars); >+ octstr_destroy(smsbox_id); > octstr_destroy(sendsms_url); > octstr_destroy(sendota_url); > octstr_destroy(xmlrpc_url); >diff -ru gateway/gw/smsc/smsc_at2.c gateway-smpp/gw/smsc/smsc_at2.c >--- gateway/gw/smsc/smsc_at2.c 2002-09-06 14:03:17.000000000 +0200 >+++ gateway-smpp/gw/smsc/smsc_at2.c 2002-09-06 15:23:16.000000000 +0200 >@@ -1682,7 +1682,8 @@ > octstr_get_cstr(msg->sms.receiver), > octstr_get_cstr(msg->sms.service), > octstr_get_cstr(msg->sms.dlr_url), >- msg->sms.dlr_mask); >+ msg->sms.dlr_mask, >+ octstr_get_cstr(msg->sms.boxc_id)); > > O_DESTROY(dlrmsgid); > } >diff -ru gateway/gw/smsc/smsc_cgw.c gateway-smpp/gw/smsc/smsc_cgw.c >--- gateway/gw/smsc/smsc_cgw.c 2002-09-04 19:06:14.000000000 +0200 >+++ gateway-smpp/gw/smsc/smsc_cgw.c 2002-09-06 15:24:14.000000000 +0200 >@@ -1127,7 +1127,8 @@ > octstr_get_cstr(msg->sms.receiver), > octstr_get_cstr(msg->sms.service), > octstr_get_cstr(msg->sms.dlr_url), >- msg->sms.dlr_mask); >+ msg->sms.dlr_mask, >+ octstr_get_cstr(msg->sms.boxc_id)); > > octstr_destroy(ts); > privdata->dlr[trn] = 1; >diff -ru gateway/gw/smsc/smsc_cimd2.c gateway-smpp/gw/smsc/smsc_cimd2.c >--- gateway/gw/smsc/smsc_cimd2.c 2002-09-04 19:06:14.000000000 +0200 >+++ gateway-smpp/gw/smsc/smsc_cimd2.c 2002-09-06 15:24:37.000000000 +0200 >@@ -1831,7 +1831,8 @@ > octstr_get_cstr(msg->sms.receiver), > octstr_get_cstr(msg->sms.service), > octstr_get_cstr(msg->sms.dlr_url), >- msg->sms.dlr_mask); >+ msg->sms.dlr_mask, >+ octstr_get_cstr(msg->sms.boxc_id)); > octstr_destroy(ts); > ts = NULL; > } >diff -ru gateway/gw/smsc/smsc_emi2.c gateway-smpp/gw/smsc/smsc_emi2.c >--- gateway/gw/smsc/smsc_emi2.c 2002-09-04 19:06:14.000000000 +0200 >+++ gateway-smpp/gw/smsc/smsc_emi2.c 2002-09-06 15:25:20.000000000 +0200 >@@ -883,7 +883,8 @@ > octstr_get_cstr(emimsg->fields[E50_ADC]), > octstr_get_cstr(msg->sms.service), > octstr_get_cstr(msg->sms.dlr_url), >- msg->sms.dlr_mask); >+ msg->sms.dlr_mask, >+ octstr_get_cstr(msg->sms.boxc_id)); > > octstr_destroy(ts); > PRIVDATA(conn)->slots[nexttrn].dlr = 1; >@@ -1020,7 +1021,8 @@ > octstr_get_cstr(adc), > octstr_get_cstr(m->sms.service), > octstr_get_cstr(m->sms.dlr_url), >- m->sms.dlr_mask); >+ m->sms.dlr_mask, >+ octstr_get_cstr(m->sms.boxc_id)); > } > octstr_destroy(ts); > octstr_destroy(adc); >diff -ru gateway/gw/smsc/smsc_fake.c gateway-smpp/gw/smsc/smsc_fake.c >--- gateway/gw/smsc/smsc_fake.c 2002-08-08 19:44:38.000000000 +0200 >+++ gateway-smpp/gw/smsc/smsc_fake.c 2002-09-06 18:05:01.000000000 +0200 >@@ -141,6 +141,13 @@ > if (octstr_url_decode(msg->sms.msgdata) == -1 || > octstr_url_decode(msg->sms.udhdata) == -1) > warning(0, "smsc_fake: urlcoded data from client looks > malformed"); >+ } >+ else if (!octstr_compare(type, octstr_imm("route"))) { >+ p2 = octstr_search_char(line, ' ', p + 1); >+ if (p2 == -1) >+ goto error; >+ msg->sms.boxc_id = octstr_copy(line, p + 1, p2 - p - 1); >+ msg->sms.msgdata = octstr_copy(line, p2 + 1, LONG_MAX); > } else > goto error; > octstr_destroy(line); >diff -ru gateway/gw/smsc/smsc_smpp.c gateway-smpp/gw/smsc/smsc_smpp.c >--- gateway/gw/smsc/smsc_smpp.c 2002-09-06 21:22:45.000000000 +0200 >+++ gateway-smpp/gw/smsc/smsc_smpp.c 2002-09-06 15:25:48.000000000 +0200 >@@ -812,7 +812,8 @@ > octstr_get_cstr(msg->sms.receiver), > octstr_get_cstr(msg->sms.service), > octstr_get_cstr(msg->sms.dlr_url), >- msg->sms.dlr_mask); >+ msg->sms.dlr_mask, >+ octstr_get_cstr(msg->sms.boxc_id)); > > /* gen DLR_SMSC_SUCCESS */ > if (msg->sms.dlr_mask & DLR_SMSC_SUCCESS) { >diff -ru gateway/gwlib/cfg.def gateway-smpp/gwlib/cfg.def >--- gateway/gwlib/cfg.def 2002-09-06 13:57:38.000000000 +0200 >+++ gateway-smpp/gwlib/cfg.def 2002-09-06 20:44:50.000000000 +0200 >@@ -1,4 +1,4 @@ >-/* >+ /* > * cfg.def - definition of configuration groups and variables > * > * Lars Wirzenius >@@ -128,6 +128,7 @@ > ) > > SINGLE_GROUP(smsbox, >+ OCTSTR(smsbox-id) > OCTSTR(bearerbox-host) > OCTSTR(sendsms-port) > OCTSTR(sendsms-port-ssl) >@@ -154,6 +155,31 @@ > OCTSTR(http-queue-delay) > ) > >+MULTI_GROUP(smsbox-route, >+ OCTSTR(smsbox-id) >+ OCTSTR(smsc-ids) >+ OCTSTR(shortcuts) >+) >+ >+ >+SINGLE_GROUP(smppbox, >+ OCTSTR(system-id) >+ OCTSTR(bearerbox-host) >+ OCTSTR(smppbox-port) >+ OCTSTR(redelivery-time) >+ OCTSTR(max-delivery-attempts) >+ OCTSTR(max-report-timeouts) >+ OCTSTR(status-cleanup-time) >+ OCTSTR(time-to-keep-status) >+ OCTSTR(max-status-objects) >+ OCTSTR(white-list) >+ OCTSTR(black-list) >+ OCTSTR(log-file) >+ OCTSTR(log-level) >+ OCTSTR(access-log) >+ OCTSTR(default-smsc) >+) >+ > > MULTI_GROUP(smsc, > OCTSTR(smsc) >@@ -289,6 +315,25 @@ > ) > > >+MULTI_GROUP(esme-user, >+ OCTSTR(username) >+ OCTSTR(password) >+ OCTSTR(mode) >+ OCTSTR(shortcuts) >+ OCTSTR(max-instances) >+ OCTSTR(default-smsc) >+ OCTSTR(force-source) >+) >+ >+ >+MULTI_GROUP(esme-route, >+ OCTSTR(username) >+ OCTSTR(allowed-prefix) >+ OCTSTR(smsc-id) >+ OCTSTR(force-source) >+) >+ >+ > MULTI_GROUP(ota-setting, > OCTSTR(ota-id) > OCTSTR(location) >diff -ru gateway/test/fakesmsc.c gateway-smpp/test/fakesmsc.c >--- gateway/test/fakesmsc.c 2001-10-08 21:43:04.000000000 +0200 >+++ gateway-smpp/test/fakesmsc.c 2002-09-06 18:03:17.000000000 +0200 >@@ -26,13 +26,14 @@ > * 'max' is the total number sent (-1, default, means unlimited),\n\ > * <msg> is message to send, if several are given, they are sent randomly.\n\ > \n\ >-msg format: \"sender receiver type(text/data/udh) [udhdata] msgdata\"\n\ >+msg format: \"sender receiver type(text/data/udh/route) [udhdata|route] >msgdata\"\n\ > \n\ > Type \"text\" means plaintext msgdata, \"data\" urlcoded, \"udh\" > urlcoded udh+msg\n\ >-\n\ >+and \"route\" means smsbox-id routed plaintext msgdata\n\ > Examples: \n\ > \n\ > fakesmsc -m 1 \"123 345 udh %04udh%3f message+data+here\"\n\ >+fakesmsc -m 1 \"123 345 route smsbox1 message+data+here\"\n\ > fakesmsc -i 0.01 -m 1000 \"123 345 text nop\" \"1 2 text another message > here\"\n\ > \n\ > Server replies are shown in the same message format.\n";