ring.c
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include <stdio.h>
00039 #include <string.h>
00040 #include <stdlib.h>
00041 #include <assert.h>
00042
00043 #include "../../parser/msg_parser.h"
00044 #include "../../dprint.h"
00045 #include "../../error.h"
00046 #include "../../ut.h"
00047 #include "../../mem/mem.h"
00048 #include "../../mem/shm_mem.h"
00049 #include "../../timer.h"
00050 #include "../../locking.h"
00051 #include "../../md5.h"
00052
00053 #include "ring.h"
00054
00055
00056
00057 struct ring_record_t {
00058 struct ring_record_t *next;
00059 unsigned int time;
00060 char callid[MAXCALLIDLEN+1];
00061 };
00062
00063
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
00071
00072 static hashtable_t *hashtable = NULL;
00073
00074 static void insert(str callid);
00075
00076 static int contains(str callid);
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
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
00108
00109
00110
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
00124
00125
00126
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
00146
00147
00148
00149
00150
00151
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
00171
00172
00173
00174
00175 static void remove_timeout(unsigned int index)
00176 {
00177 while ((*hashtable)[index].head && ((*hashtable)[index].head)->time + ring_timeout < get_ticks()) {
00178 struct ring_record_t* rr = (*hashtable)[index].head;
00179 (*hashtable)[index].head = rr->next;
00180 if ((*hashtable)[index].head == NULL) (*hashtable)[index].tail = NULL;
00181 LM_DBG("deleting ticks=%d %s\n", get_ticks(), rr->callid);
00182 shm_free(rr);
00183 }
00184 }
00185
00186
00187
00188
00189
00190
00191 static void insert(str callid)
00192 {
00193 unsigned int index = hash(callid.s, callid.len) & HASHTABLEMASK;
00194
00195 remove_timeout(index);
00196
00197 struct ring_record_t* rr = shm_malloc(sizeof(struct ring_record_t));
00198 assert(rr);
00199
00200 rr->next = NULL;
00201 rr->time = get_ticks();
00202 strncpy(rr->callid, callid.s, MIN(callid.len, MAXCALLIDLEN));
00203 rr->callid[MIN(callid.len, MAXCALLIDLEN)] = 0;
00204
00205 if ((*hashtable)[index].tail) {
00206 (*hashtable)[index].tail->next = rr;
00207 (*hashtable)[index].tail = rr;
00208 }
00209 else {
00210 (*hashtable)[index].head = rr;
00211 (*hashtable)[index].tail = rr;
00212 }
00213
00214 LM_DBG("inserting at %d %.*s ticks=%d\n", index, callid.len, callid.s, rr->time);
00215 }
00216
00217
00218
00219
00220
00221
00222
00223 static int contains(str callid)
00224 {
00225 unsigned int index = hash(callid.s, callid.len) & HASHTABLEMASK;
00226
00227 remove_timeout(index);
00228
00229 struct ring_record_t* rr = (*hashtable)[index].head;
00230 while (rr) {
00231 if (strncmp(rr->callid, callid.s, callid.len) == 0) return 1;
00232 rr = rr->next;
00233 }
00234 return 0;
00235 }
00236
00237
00238
00239
00240
00241
00242 static int conv183(struct sip_msg *msg)
00243 {
00244
00245 char *del1_start = strstr(msg->buf, "Content-Length:");
00246 char *del2_start = strstr(msg->buf, "Content-Type:");
00247 if (del1_start>del2_start) {
00248 char *tmp = del1_start;
00249 del1_start = del2_start;
00250 del2_start = tmp;
00251 }
00252
00253 char *del1_end = NULL;
00254 if (del1_start) {
00255 del1_end = strstr(del1_start, "\r\n");
00256 if (del1_end) del1_end+=2;
00257 }
00258 char *del2_end = NULL;
00259 if (del2_start) {
00260 del2_end = strstr(del2_start, "\r\n");
00261 if (del2_end) del2_end+=2;
00262 }
00263
00264
00265 char *eoh = strstr(msg->buf, "\r\n\r\n");
00266 if (eoh) eoh+=2;
00267
00268 if ((!del1_start) || (!del2_start) || (!del1_end) || (!del2_end) || (!eoh)) {
00269 LM_ERR("got invalid 183 message\n");
00270 return -1;
00271 }
00272
00273
00274
00275
00276
00277
00278 if (msg->unparsed>del1_start) {
00279 LM_ERR("183 message got parsed too far!\n");
00280 return -1;
00281 }
00282
00283
00284 msg->first_line.u.reply.statuscode=180;
00285 msg->first_line.u.reply.status.s[2]='0';
00286
00287 strncpy(msg->first_line.u.reply.reason.s, "Ringing ", msg->first_line.u.reply.reason.len);
00288
00289
00290 char *chunk1_start = del1_end;
00291 int chunk1_len = del2_start-del1_end;
00292 char *chunk1_dst = del1_start;
00293
00294 char *chunk2_start = del2_end;
00295 int chunk2_len = eoh-del2_end;
00296 char *chunk2_dst = chunk1_dst+chunk1_len;
00297
00298 char *chunk3_start = "Content-Length: 0\r\n\r\n";
00299 int chunk3_len = strlen(chunk3_start);
00300 char *chunk3_dst = chunk2_dst+chunk2_len;
00301
00302
00303 memmove(chunk1_dst, chunk1_start, chunk1_len);
00304 memmove(chunk2_dst, chunk2_start, chunk2_len);
00305 memmove(chunk3_dst, chunk3_start, chunk3_len);
00306
00307
00308 *(chunk3_dst+chunk3_len)='\0';
00309
00310
00311 msg->len = strlen(msg->buf);
00312
00313 return 0;
00314 }
00315
00316
00317
00318
00319
00320
00321
00322
00323 int ring_filter(struct sip_msg *msg, void *bar)
00324 {
00325 int contains_callid;
00326
00327 if (msg->first_line.type == SIP_REPLY && msg->first_line.u.reply.statuscode == 183) {
00328
00329 parse_headers(msg, HDR_CALLID_F, 0);
00330
00331 if (msg->callid) {
00332 lock_get(ring_lock);
00333 contains_callid=contains(msg->callid->body);
00334 lock_release(ring_lock);
00335
00336 if (contains_callid) {
00337 LM_DBG("converting 183 to 180 for %.*s\n", msg->callid->body.len, msg->callid->body.s);
00338 if (conv183(msg)!=0) return -1;
00339 }
00340 } else {
00341 LM_ERR("no callid\n");
00342 return -1;
00343 }
00344 }
00345
00346 return 1;
00347 }
00348
00349
00350
00351
00352
00353
00354
00355
00356 int ring_fixup(void ** param, int param_no) {
00357 if (ring_timeout == 0) {
00358 LM_ERR("ring_insert_callid functionality deactivated, you need to set a positive ring_timeout\n");
00359 return -1;
00360 }
00361 return 0;
00362 }