00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00037 #include <stdio.h>
00038 #include <string.h>
00039 #include <stdlib.h>
00040 #include <assert.h>
00041
00042 #include "../../parser/msg_parser.h"
00043 #include "../../dprint.h"
00044 #include "../../error.h"
00045 #include "../../ut.h"
00046 #include "../../mem/mem.h"
00047 #include "../../mem/shm_mem.h"
00048 #include "../../timer.h"
00049 #include "../../locking.h"
00050 #include "../../md5.h"
00051
00052 #include "config.h"
00053 #include "ring.h"
00054
00055
00057 struct ring_record_t {
00058 struct ring_record_t *next;
00059 unsigned int time;
00060 char callid[MAXCALLIDLEN+1];
00061 };
00062
00064 struct hashtable_entry_t {
00065 struct ring_record_t *head;
00066 struct ring_record_t *tail;
00067 };
00068
00069 typedef struct hashtable_entry_t hashtable_t[HASHTABLESIZE];
00070
00072 static hashtable_t *hashtable = NULL;
00073
00074 static void insert(str callid);
00075
00076 static int contains(str callid);
00077
00078
00090 int ring_insert_callid(struct sip_msg *msg, char *unused1, char *unused2)
00091 {
00092
00093 parse_headers(msg, HDR_CALLID_F, 0);
00094
00095 if (msg->callid) {
00096 lock_get(ring_lock);
00097 if (!contains(msg->callid->body)) insert(msg->callid->body);
00098 lock_release(ring_lock);
00099 } else {
00100 LM_ERR("no callid\n");
00101 return -1;
00102 }
00103
00104 return 1;
00105 }
00106
00107
00111 void ring_init_hashtable(void)
00112 {
00113 int i;
00114
00115 hashtable = shm_malloc(sizeof(hashtable_t));
00116 assert(hashtable);
00117 for (i=0; i<HASHTABLESIZE; i++) {
00118 (*hashtable)[i].head = NULL;
00119 (*hashtable)[i].tail = NULL;
00120 }
00121 }
00122
00123
00127 void ring_destroy_hashtable(void)
00128 {
00129 int i;
00130
00131 if (hashtable) {
00132 for (i=0; i<HASHTABLESIZE; i++) {
00133 while ((*hashtable)[i].head) {
00134 struct ring_record_t* rr = (*hashtable)[i].head;
00135 (*hashtable)[i].head = rr->next;
00136 shm_free(rr);
00137 }
00138 (*hashtable)[i].tail = NULL;
00139 }
00140
00141 shm_free(hashtable);
00142 }
00143 }
00144
00145
00152 static unsigned int hash(char *buf, int len)
00153 {
00154 int i;
00155 unsigned int retval = 0;
00156 MD5_CTX md5context;
00157 char digest[16];
00158
00159 MD5Init(&md5context);
00160 MD5Update(&md5context, buf, len);
00161 MD5Final(digest, &md5context);
00162
00163 for (i=0; i<16; i++) {
00164 retval ^= ((unsigned int)((unsigned char)buf[i])) << i;
00165 }
00166
00167 return retval;
00168 }
00169
00170
00175 static void remove_timeout(unsigned int index)
00176 {
00177 int ring_timeout = cfg_get(siputils, siputils_cfg, ring_timeout);
00178 if(ring_timeout == 0){
00179 LM_ERR("Could not get timeout from cfg. This will expire all entries");
00180 }
00181 while ((*hashtable)[index].head && ((*hashtable)[index].head)->time + ring_timeout < get_ticks()) {
00182 struct ring_record_t* rr = (*hashtable)[index].head;
00183 (*hashtable)[index].head = rr->next;
00184 if ((*hashtable)[index].head == NULL) (*hashtable)[index].tail = NULL;
00185 LM_DBG("deleting ticks=%d %s\n", get_ticks(), rr->callid);
00186 shm_free(rr);
00187 }
00188 }
00189
00190
00195 static void insert(str callid)
00196 {
00197 unsigned int index = hash(callid.s, callid.len) & HASHTABLEMASK;
00198 struct ring_record_t* rr;
00199
00200 remove_timeout(index);
00201 rr = shm_malloc(sizeof(struct ring_record_t));
00202 assert(rr);
00203
00204 rr->next = NULL;
00205 rr->time = get_ticks();
00206 strncpy(rr->callid, callid.s, MIN(callid.len, MAXCALLIDLEN));
00207 rr->callid[MIN(callid.len, MAXCALLIDLEN)] = 0;
00208
00209 if ((*hashtable)[index].tail) {
00210 (*hashtable)[index].tail->next = rr;
00211 (*hashtable)[index].tail = rr;
00212 }
00213 else {
00214 (*hashtable)[index].head = rr;
00215 (*hashtable)[index].tail = rr;
00216 }
00217
00218 LM_DBG("inserting at %d %.*s ticks=%d\n", index, callid.len, callid.s, rr->time);
00219 }
00220
00221
00227 static int contains(str callid)
00228 {
00229 unsigned int index = hash(callid.s, callid.len) & HASHTABLEMASK;
00230 struct ring_record_t* rr;
00231
00232 remove_timeout(index);
00233
00234 rr = (*hashtable)[index].head;
00235 while (rr) {
00236 if (strncmp(rr->callid, callid.s, callid.len) == 0) return 1;
00237 rr = rr->next;
00238 }
00239 return 0;
00240 }
00241
00242
00247 static int conv183(struct sip_msg *msg)
00248 {
00249
00250 char *del1_start = strstr(msg->buf, "Content-Length:");
00251 char *del2_start = strstr(msg->buf, "Content-Type:");
00252 char *del1_end;
00253 char *del2_end;
00254 char *eoh;
00255 char *chunk1_start;
00256 int chunk1_len;
00257 char *chunk1_dst;
00258 char *chunk2_start;
00259 int chunk2_len;
00260 char *chunk2_dst;
00261 char *chunk3_start;
00262 int chunk3_len;
00263 char *chunk3_dst;
00264
00265 if (del1_start>del2_start) {
00266 char *tmp = del1_start;
00267 del1_start = del2_start;
00268 del2_start = tmp;
00269 }
00270
00271 del1_end = NULL;
00272 if (del1_start) {
00273 del1_end = strstr(del1_start, "\r\n");
00274 if (del1_end) del1_end+=2;
00275 }
00276 del2_end = NULL;
00277 if (del2_start) {
00278 del2_end = strstr(del2_start, "\r\n");
00279 if (del2_end) del2_end+=2;
00280 }
00281
00282
00283 eoh = strstr(msg->buf, "\r\n\r\n");
00284 if (eoh) eoh+=2;
00285
00286 if ((!del1_start) || (!del2_start) || (!del1_end) || (!del2_end) || (!eoh)) {
00287 LM_ERR("got invalid 183 message\n");
00288 return -1;
00289 }
00290
00291
00292
00293
00294
00295
00296 if (msg->unparsed>del1_start) {
00297 LM_ERR("183 message got parsed too far!\n");
00298 return -1;
00299 }
00300
00301
00302 msg->first_line.u.reply.statuscode=180;
00303 msg->first_line.u.reply.status.s[2]='0';
00304
00305 strncpy(msg->first_line.u.reply.reason.s, "Ringing ", msg->first_line.u.reply.reason.len);
00306
00307
00308 chunk1_start = del1_end;
00309 chunk1_len = (int)(long)(del2_start-del1_end);
00310 chunk1_dst = del1_start;
00311
00312 chunk2_start = del2_end;
00313 chunk2_len = (int)(long)(eoh-del2_end);
00314 chunk2_dst = chunk1_dst+chunk1_len;
00315
00316 chunk3_start = "Content-Length: 0\r\n\r\n";
00317 chunk3_len = strlen(chunk3_start);
00318 chunk3_dst = chunk2_dst+chunk2_len;
00319
00320
00321 memmove(chunk1_dst, chunk1_start, chunk1_len);
00322 memmove(chunk2_dst, chunk2_start, chunk2_len);
00323 memmove(chunk3_dst, chunk3_start, chunk3_len);
00324
00325
00326 *(chunk3_dst+chunk3_len)='\0';
00327
00328
00329 msg->len = strlen(msg->buf);
00330
00331 return 0;
00332 }
00333
00334
00342 int ring_filter(struct sip_msg *msg, unsigned int flags, void *bar)
00343 {
00344 int contains_callid;
00345
00346 if (msg->first_line.type == SIP_REPLY && msg->first_line.u.reply.statuscode == 183) {
00347
00348 parse_headers(msg, HDR_CALLID_F, 0);
00349
00350 if (msg->callid) {
00351 lock_get(ring_lock);
00352 contains_callid=contains(msg->callid->body);
00353 lock_release(ring_lock);
00354
00355 if (contains_callid) {
00356 LM_DBG("converting 183 to 180 for %.*s\n", msg->callid->body.len, msg->callid->body.s);
00357 if (conv183(msg)!=0) return -1;
00358 }
00359 } else {
00360 LM_ERR("no callid\n");
00361 return -1;
00362 }
00363 }
00364
00365 return 1;
00366 }
00367
00368
00375 int ring_fixup(void ** param, int param_no) {
00376 int ring_timeout = cfg_get(siputils, siputils_cfg, ring_timeout);
00377 if (ring_timeout == 0) {
00378 LM_ERR("ring_insert_callid functionality deactivated, you need to set a positive ring_timeout\n");
00379 return -1;
00380 }
00381 return 0;
00382 }