diff --git a/src/modules/seas/cluster.c b/src/modules/seas/cluster.c index 4eeadcb87d7..214399540c3 100644 --- a/src/modules/seas/cluster.c +++ b/src/modules/seas/cluster.c @@ -29,9 +29,10 @@ char *cluster_cfg; -#define eat_spaces(_p) \ - while( *(_p)==' ' || *(_p)=='\t' ){\ - (_p)++;} +#define eat_spaces(_p) \ + while(*(_p) == ' ' || *(_p) == '\t') { \ + (_p)++; \ + } /** @@ -48,136 +49,139 @@ char *cluster_cfg; */ int parse_cluster_cfg(void) { - char *p,*start; - int n,k; - struct as_entry **entry,*tmp,*tmp2; + char *p, *start; + int n, k; + struct as_entry **entry, *tmp, *tmp2; - if((p=cluster_cfg)==0 || *cluster_cfg==0){ - return 0; - } - entry=&as_list; + if((p = cluster_cfg) == 0 || *cluster_cfg == 0) { + return 0; + } + entry = &as_list; - while (*p) - { - eat_spaces(p); - /*get cluster name*/ - start = p; - while (*p!=' ' && *p!='\t' && *p!='[' && *p!=0) - p++; - if ( p==start || *p==0 ){ - LM_ERR("cluster names must only contain alphanumeric chars\n"); - goto error; - } - if (!((*entry)=(struct as_entry*)shm_malloc(sizeof(struct as_entry)))) { - LM_ERR("Out of shm mem for as_entry\n"); - goto error; - } - memset(*entry,0,sizeof(struct as_entry)); - if (!((*entry)->name.s=shm_malloc(p-start))) { - LM_ERR("Out of shm malloc for cluster name\n"); - goto error; - } - memcpy((*entry)->name.s, start, p-start); - (*entry)->name.len=p-start; - (*entry)->connected=0; - (*entry)->type=CLUSTER_TYPE; - (*entry)->u.cs.name=(*entry)->name; - /*get as names*/ - eat_spaces(p); - if (*p!='['){ - LM_ERR("Malformed cluster cfg string %s\n",cluster_cfg); - goto error; - } - p++; - n=0; - while (*p!=']') - { - eat_spaces(p); - start = p; - while(*p!=' ' && *p!='\t' && *p!=']' && *p!=',' && *p!=0) - p++; - if ( p==start || *p==0 ) - goto error; - if (!((*entry)->u.cs.as_names[n].s=shm_malloc(p-start))) { - LM_ERR("Out of shm_mem for AS name in cluster\n"); - goto error; - } - (*entry)->u.cs.as_names[n].len=p-start; - memcpy((*entry)->u.cs.as_names[n].s,start,p-start); - n++; - if(n>=MAX_AS_PER_CLUSTER){ - LM_ERR("too many AS per cluster\n"); - goto error; - } - eat_spaces(p); - if (*p==',') { - p++; - eat_spaces(p); - } - } - p++; - (*entry)->u.cs.num=n; - /* end of element */ - eat_spaces(p); - if (*p==',') - p++; - eat_spaces(p); - entry=&((*entry)->next); - } - for (tmp=as_list;tmp->next;tmp=tmp->next){ - LM_DBG("%.*s\n",tmp->name.len,tmp->name.s); - } - LM_DBG("%.*s\n",tmp->name.len,tmp->name.s); - entry=&(tmp->next); - for(tmp=as_list;tmp;tmp=tmp->next){ - if (tmp->type!=CLUSTER_TYPE) - continue; - LM_DBG("cluster:[%.*s]\n",tmp->name.len,tmp->name.s); - for(k=0;ku.cs.num;k++){ - LM_DBG("\tAS:[%.*s]\n",tmp->u.cs.as_names[k].len,tmp->u.cs.as_names[k].s); - for (tmp2=as_list;tmp2;tmp2=tmp2->next) { - if (tmp2->type== AS_TYPE && tmp->u.cs.as_names[k].len == tmp2->name.len && - !memcmp(tmp->u.cs.as_names[k].s,tmp2->name.s,tmp2->name.len)) { - tmp->u.cs.servers[k]=&tmp2->u.as; - break; - } - } - if(tmp2) - continue; - if (!((*entry)=shm_malloc(sizeof(struct as_entry)))) { - LM_ERR("Out of shm mem \n"); - goto error; - } - memset(*entry,0,sizeof(struct as_entry)); - (*entry)->type=AS_TYPE; - if (!((*entry)->name.s=shm_malloc(tmp->u.cs.as_names[k].len))) { - LM_ERR("out of shm mem\n"); - goto error; - } - memcpy((*entry)->name.s,tmp->u.cs.as_names[k].s,tmp->u.cs.as_names[k].len); - (*entry)->name.len=tmp->u.cs.as_names[k].len; - (*entry)->u.as.name=(*entry)->name; - tmp->u.cs.servers[k]=&(*entry)->u.as; - entry=&((*entry)->next); - } - } - for(tmp=as_list;tmp;tmp=tmp->next){ - LM_DBG("%.*s %s",tmp->name.len,tmp->name.s,tmp->next?"":"\n"); - } - return 1; + while(*p) { + eat_spaces(p); + /*get cluster name*/ + start = p; + while(*p != ' ' && *p != '\t' && *p != '[' && *p != 0) + p++; + if(p == start || *p == 0) { + LM_ERR("cluster names must only contain alphanumeric chars\n"); + goto error; + } + if(!((*entry) = (struct as_entry *)shm_malloc( + sizeof(struct as_entry)))) { + LM_ERR("Out of shm mem for as_entry\n"); + goto error; + } + memset(*entry, 0, sizeof(struct as_entry)); + if(!((*entry)->name.s = shm_malloc(p - start))) { + LM_ERR("Out of shm malloc for cluster name\n"); + goto error; + } + memcpy((*entry)->name.s, start, p - start); + (*entry)->name.len = p - start; + (*entry)->connected = 0; + (*entry)->type = CLUSTER_TYPE; + (*entry)->u.cs.name = (*entry)->name; + /*get as names*/ + eat_spaces(p); + if(*p != '[') { + LM_ERR("Malformed cluster cfg string %s\n", cluster_cfg); + goto error; + } + p++; + n = 0; + while(*p != ']') { + eat_spaces(p); + start = p; + while(*p != ' ' && *p != '\t' && *p != ']' && *p != ',' && *p != 0) + p++; + if(p == start || *p == 0) + goto error; + if(!((*entry)->u.cs.as_names[n].s = shm_malloc(p - start))) { + LM_ERR("Out of shm_mem for AS name in cluster\n"); + goto error; + } + (*entry)->u.cs.as_names[n].len = p - start; + memcpy((*entry)->u.cs.as_names[n].s, start, p - start); + n++; + if(n >= MAX_AS_PER_CLUSTER) { + LM_ERR("too many AS per cluster\n"); + goto error; + } + eat_spaces(p); + if(*p == ',') { + p++; + eat_spaces(p); + } + } + p++; + (*entry)->u.cs.num = n; + /* end of element */ + eat_spaces(p); + if(*p == ',') + p++; + eat_spaces(p); + entry = &((*entry)->next); + } + for(tmp = as_list; tmp->next; tmp = tmp->next) { + LM_DBG("%.*s\n", tmp->name.len, tmp->name.s); + } + LM_DBG("%.*s\n", tmp->name.len, tmp->name.s); + entry = &(tmp->next); + for(tmp = as_list; tmp; tmp = tmp->next) { + if(tmp->type != CLUSTER_TYPE) + continue; + LM_DBG("cluster:[%.*s]\n", tmp->name.len, tmp->name.s); + for(k = 0; k < tmp->u.cs.num; k++) { + LM_DBG("\tAS:[%.*s]\n", tmp->u.cs.as_names[k].len, + tmp->u.cs.as_names[k].s); + for(tmp2 = as_list; tmp2; tmp2 = tmp2->next) { + if(tmp2->type == AS_TYPE + && tmp->u.cs.as_names[k].len == tmp2->name.len + && !memcmp(tmp->u.cs.as_names[k].s, tmp2->name.s, + tmp2->name.len)) { + tmp->u.cs.servers[k] = &tmp2->u.as; + break; + } + } + if(tmp2) + continue; + if(!((*entry) = shm_malloc(sizeof(struct as_entry)))) { + LM_ERR("Out of shm mem \n"); + goto error; + } + memset(*entry, 0, sizeof(struct as_entry)); + (*entry)->type = AS_TYPE; + if(!((*entry)->name.s = shm_malloc(tmp->u.cs.as_names[k].len))) { + LM_ERR("out of shm mem\n"); + goto error; + } + memcpy((*entry)->name.s, tmp->u.cs.as_names[k].s, + tmp->u.cs.as_names[k].len); + (*entry)->name.len = tmp->u.cs.as_names[k].len; + (*entry)->u.as.name = (*entry)->name; + tmp->u.cs.servers[k] = &(*entry)->u.as; + entry = &((*entry)->next); + } + } + for(tmp = as_list; tmp; tmp = tmp->next) { + LM_DBG("%.*s %s", tmp->name.len, tmp->name.s, tmp->next ? "" : "\n"); + } + return 1; error: - tmp=as_list; - while(tmp){ - for(k=0;ku.cs.num;k++){ - if(tmp->u.cs.as_names[k].s) - shm_free(tmp->u.cs.as_names[k].s); - } - if(tmp->name.s) - shm_free(tmp->name.s); - tmp2=tmp; - tmp=tmp->next; - shm_free(tmp2); - } - as_list=(struct as_entry *)0; - return -1; + tmp = as_list; + while(tmp) { + for(k = 0; k < tmp->u.cs.num; k++) { + if(tmp->u.cs.as_names[k].s) + shm_free(tmp->u.cs.as_names[k].s); + } + if(tmp->name.s) + shm_free(tmp->name.s); + tmp2 = tmp; + tmp = tmp->next; + shm_free(tmp2); + } + as_list = (struct as_entry *)0; + return -1; } diff --git a/src/modules/seas/encode_allow.c b/src/modules/seas/encode_allow.c index 3d5f2820dce..984f8e1ffad 100644 --- a/src/modules/seas/encode_allow.c +++ b/src/modules/seas/encode_allow.c @@ -46,35 +46,38 @@ #include "../../core/parser/msg_parser.h" #include "encode_allow.h" -char *mismetodos[]={"UNDEF","INVITE","CANCEL","ACK","BYE","INFO","OPTIONS","UPDATE","REGISTER","MESSAGE","SUBSCRIBE","NOTIFY","PRACK","REFER","OTHER"}; +char *mismetodos[] = {"UNDEF", "INVITE", "CANCEL", "ACK", "BYE", "INFO", + "OPTIONS", "UPDATE", "REGISTER", "MESSAGE", "SUBSCRIBE", "NOTIFY", + "PRACK", "REFER", "OTHER"}; /** * Encodes allow header. * * TODO: Does not support the UNDEFINED header type !!! */ -int encode_allow(char *hdrstart,int hdrlen,unsigned int *bodi,char *where) +int encode_allow(char *hdrstart, int hdrlen, unsigned int *bodi, char *where) { - unsigned int i; - memcpy(&i,bodi,4); - i=htonl(i); - memcpy(where,&i,4); - return 4; + unsigned int i; + memcpy(&i, bodi, 4); + i = htonl(i); + memcpy(where, &i, 4); + return 4; } -int print_encoded_allow(FILE *fd,char *hdr,int hdrlen,unsigned char* payload,int paylen,char *prefix) +int print_encoded_allow(FILE *fd, char *hdr, int hdrlen, unsigned char *payload, + int paylen, char *prefix) { - unsigned int i,j=0,body; + unsigned int i, j = 0, body; - memcpy(&body,payload,4); - body=ntohl(body); - fprintf(fd,"%sMETHODS=",prefix); - if(body==0) - fprintf(fd,"UNKNOWN"); - for(i=0;i<32;j=(0x01<star){ - flags|=STAR_F; - where[0]=flags; - return 1; - } - for(contact_offset=0,i=0,mycontact=contact_parsed->contacts;mycontact;mycontact=mycontact->next,i++){ - if((k=encode_contact(hdr,hdrlen,mycontact,&tmp[contact_offset]))<0){ - LM_ERR("parsing contact number %d\n",i); - return -1; - } - where[2+i]=k; - contact_offset+=k; - } - where[1]=(unsigned char)i; - memcpy(&where[2+i],tmp,contact_offset); - return 2+i+contact_offset; + if(contact_parsed->star) { + flags |= STAR_F; + where[0] = flags; + return 1; + } + for(contact_offset = 0, i = 0, mycontact = contact_parsed->contacts; + mycontact; mycontact = mycontact->next, i++) { + if((k = encode_contact(hdr, hdrlen, mycontact, &tmp[contact_offset])) + < 0) { + LM_ERR("parsing contact number %d\n", i); + return -1; + } + where[2 + i] = k; + contact_offset += k; + } + where[1] = (unsigned char)i; + memcpy(&where[2 + i], tmp, contact_offset); + return 2 + i + contact_offset; } /* Encoder for contacts. @@ -107,211 +110,235 @@ int encode_contact_body(char *hdr,int hdrlen,contact_body_t *contact_parsed,unsi * [N:] optionally, HDR-based pointers to the different header-parameters * */ -int encode_contact(char *hdrstart,int hdrlen,contact_t *body,unsigned char *where) +int encode_contact( + char *hdrstart, int hdrlen, contact_t *body, unsigned char *where) { - int i=2,j=0;/* 1*flags + 1*URI_len*/ - unsigned char flags=0; - struct sip_uri puri; + int i = 2, j = 0; /* 1*flags + 1*URI_len*/ + unsigned char flags = 0; + struct sip_uri puri; - if(body->name.s && body->name.len){ - flags|=HAS_NAME_F; - where[i++]=(unsigned char)(body->name.s-hdrstart); - where[i++]=(unsigned char)body->name.len; - } - if(body->q){ - flags|=HAS_Q_F; - where[i++]=(unsigned char)(body->q->name.s-hdrstart); - where[i++]=(unsigned char)body->q->len; - } - if(body->expires){ - flags|=HAS_EXPIRES_F; - where[i++]=(unsigned char)(body->expires->name.s-hdrstart); - where[i++]=(unsigned char)body->expires->len; - } - if(body->received){ - flags|=HAS_RECEIVED_F; - where[i++]=(unsigned char)(body->received->name.s-hdrstart); - where[i++]=(unsigned char)body->received->len; - } - if(body->methods){ - flags|=HAS_METHOD_F; - where[i++]=(unsigned char)(body->methods->name.s-hdrstart); - where[i++]=(unsigned char)body->methods->len; - } + if(body->name.s && body->name.len) { + flags |= HAS_NAME_F; + where[i++] = (unsigned char)(body->name.s - hdrstart); + where[i++] = (unsigned char)body->name.len; + } + if(body->q) { + flags |= HAS_Q_F; + where[i++] = (unsigned char)(body->q->name.s - hdrstart); + where[i++] = (unsigned char)body->q->len; + } + if(body->expires) { + flags |= HAS_EXPIRES_F; + where[i++] = (unsigned char)(body->expires->name.s - hdrstart); + where[i++] = (unsigned char)body->expires->len; + } + if(body->received) { + flags |= HAS_RECEIVED_F; + where[i++] = (unsigned char)(body->received->name.s - hdrstart); + where[i++] = (unsigned char)body->received->len; + } + if(body->methods) { + flags |= HAS_METHOD_F; + where[i++] = (unsigned char)(body->methods->name.s - hdrstart); + where[i++] = (unsigned char)body->methods->len; + } - if (parse_uri(body->uri.s, body->uri.len,&puri) < 0 ) { - LM_ERR("Bad URI in address\n"); - return -1; - }else{ - if((j=encode_uri2(hdrstart,hdrlen,body->uri,&puri,&where[i]))<0){ - LM_ERR("failed to codify the URI\n"); - return -1; - }else{ - i+=j; - } - } - where[0]=flags; - where[1]=(unsigned char)j; - /*CAUTION the parameters are in reversed order !!! */ - /*TODO parameter encoding logic should be moved to a specific function...*/ + if(parse_uri(body->uri.s, body->uri.len, &puri) < 0) { + LM_ERR("Bad URI in address\n"); + return -1; + } else { + if((j = encode_uri2(hdrstart, hdrlen, body->uri, &puri, &where[i])) + < 0) { + LM_ERR("failed to codify the URI\n"); + return -1; + } else { + i += j; + } + } + where[0] = flags; + where[1] = (unsigned char)j; + /*CAUTION the parameters are in reversed order !!! */ + /*TODO parameter encoding logic should be moved to a specific function...*/ - i+=encode_parameters(&where[i],body->params,hdrstart,body,'n'); - return i; + i += encode_parameters(&where[i], body->params, hdrstart, body, 'n'); + return i; } -int print_encoded_contact_body(FILE *fd,char *hdr,int hdrlen,unsigned char *payload,int paylen,char *prefix) +int print_encoded_contact_body(FILE *fd, char *hdr, int hdrlen, + unsigned char *payload, int paylen, char *prefix) { - unsigned char flags, numcontacts; - int i,offset; + unsigned char flags, numcontacts; + int i, offset; - flags=payload[0]; - fprintf(fd,"%s",prefix); - for(i=0;itype.s-hdrstart); - where[2]=(unsigned char)body->type.len; - i+=encode_parameters(&where[3],(void *)body->params,hdrstart,body,'d'); - return i; + /*where[0] reserved flags for future use*/ + where[1] = (unsigned char)(body->type.s - hdrstart); + where[2] = (unsigned char)body->type.len; + i += encode_parameters( + &where[3], (void *)body->params, hdrstart, body, 'd'); + return i; } -int print_encoded_content_disposition(FILE* fd,char *hdr,int hdrlen,unsigned char* payload,int paylen,char *prefix) +int print_encoded_content_disposition(FILE *fd, char *hdr, int hdrlen, + unsigned char *payload, int paylen, char *prefix) { - int i=3;/* flags + urilength */ + int i = 3; /* flags + urilength */ - fprintf(fd,"%s",prefix); - for(i=0;i>16){ - case TYPE_TEXT: - chtype="text"; - break; - case TYPE_MESSAGE: - chtype="message"; - break; - case TYPE_APPLICATION: - chtype="application"; - break; - case TYPE_MULTIPART: - chtype="multipart"; - break; - case TYPE_ALL: - chtype="all"; - break; - case TYPE_UNKNOWN: - chtype="unknown"; - break; - default: - chtype="(didn't know this type existed)"; - break; - } - - switch(type&0xFF){ - case SUBTYPE_PLAIN: - chsubtype="SUBTYPE_PLAIN"; - break; - case SUBTYPE_CPIM: - chsubtype="SUBTYPE_CPIM"; - break; - case SUBTYPE_SDP: - chsubtype="SUBTYPE_SDP"; - break; - case SUBTYPE_CPLXML: - chsubtype="SUBTYPE_CPLXML"; - break; - case SUBTYPE_PIDFXML: - chsubtype="SUBTYPE_PIDFXML"; - break; - case SUBTYPE_RLMIXML: - chsubtype="SUBTYPE_RLMIXML"; - break; - case SUBTYPE_RELATED: - chsubtype="SUBTYPE_RELATED"; - break; - case SUBTYPE_LPIDFXML: - chsubtype="SUBTYPE_LPIDFXML"; - break; - case SUBTYPE_XPIDFXML: - chsubtype="SUBTYPE_XPIDFXML"; - break; - case SUBTYPE_WATCHERINFOXML: - chsubtype="SUBTYPE_WATCHERINFOXML"; - break; - case SUBTYPE_EXTERNAL_BODY: - chsubtype="SUBTYPE_EXTERNAL_BODY"; - break; - case SUBTYPE_XML_MSRTC_PIDF: - chsubtype="SUBTYPE_XML_MSRTC_PIDF"; - break; - case SUBTYPE_ALL: - chsubtype="SUBTYPE_ALL"; - break; - case SUBTYPE_UNKNOWN: - chsubtype="SUBTYPE_UNKNOWN"; - break; - default: - chsubtype="(didn't know this subtype existed)"; - } - - fprintf(fd,"%sTYPE:[%s]\n",prefix,chtype); - fprintf(fd,"%sSUBTYPE:[%s]\n",prefix,chsubtype); - return 0; + unsigned int type; + char *chtype, *chsubtype; + + type = ntohl(*payload); + + switch(type >> 16) { + case TYPE_TEXT: + chtype = "text"; + break; + case TYPE_MESSAGE: + chtype = "message"; + break; + case TYPE_APPLICATION: + chtype = "application"; + break; + case TYPE_MULTIPART: + chtype = "multipart"; + break; + case TYPE_ALL: + chtype = "all"; + break; + case TYPE_UNKNOWN: + chtype = "unknown"; + break; + default: + chtype = "(didn't know this type existed)"; + break; + } + + switch(type & 0xFF) { + case SUBTYPE_PLAIN: + chsubtype = "SUBTYPE_PLAIN"; + break; + case SUBTYPE_CPIM: + chsubtype = "SUBTYPE_CPIM"; + break; + case SUBTYPE_SDP: + chsubtype = "SUBTYPE_SDP"; + break; + case SUBTYPE_CPLXML: + chsubtype = "SUBTYPE_CPLXML"; + break; + case SUBTYPE_PIDFXML: + chsubtype = "SUBTYPE_PIDFXML"; + break; + case SUBTYPE_RLMIXML: + chsubtype = "SUBTYPE_RLMIXML"; + break; + case SUBTYPE_RELATED: + chsubtype = "SUBTYPE_RELATED"; + break; + case SUBTYPE_LPIDFXML: + chsubtype = "SUBTYPE_LPIDFXML"; + break; + case SUBTYPE_XPIDFXML: + chsubtype = "SUBTYPE_XPIDFXML"; + break; + case SUBTYPE_WATCHERINFOXML: + chsubtype = "SUBTYPE_WATCHERINFOXML"; + break; + case SUBTYPE_EXTERNAL_BODY: + chsubtype = "SUBTYPE_EXTERNAL_BODY"; + break; + case SUBTYPE_XML_MSRTC_PIDF: + chsubtype = "SUBTYPE_XML_MSRTC_PIDF"; + break; + case SUBTYPE_ALL: + chsubtype = "SUBTYPE_ALL"; + break; + case SUBTYPE_UNKNOWN: + chsubtype = "SUBTYPE_UNKNOWN"; + break; + default: + chsubtype = "(didn't know this subtype existed)"; + } + + fprintf(fd, "%sTYPE:[%s]\n", prefix, chtype); + fprintf(fd, "%sSUBTYPE:[%s]\n", prefix, chsubtype); + return 0; } diff --git a/src/modules/seas/encode_content_type.h b/src/modules/seas/encode_content_type.h index b3d359c86a6..f6255a3e50b 100644 --- a/src/modules/seas/encode_content_type.h +++ b/src/modules/seas/encode_content_type.h @@ -20,10 +20,15 @@ #ifndef __ENCODE_CONTENT_TYPE_H__ #define __ENCODE_CONTENT_TYPE_H__ -int encode_content_type(char *hdrstart,int hdrlen,unsigned int bodi,char *where); -int encode_accept(char *hdrstart,int hdrlen,unsigned int *bodi,char *where); -int encode_mime_type(char *hdrstart,int hdrlen,unsigned int bodi,char *where); -int print_encoded_mime_type(FILE* fd,char *hdr,int hdrlen,unsigned int* payload,int paylen,char *prefix); -int print_encoded_content_type(FILE* fd,char *hdr,int hdrlen,unsigned char* payload,int paylen,char *prefix); -int print_encoded_accept(FILE* fd,char *hdr,int hdrlen,unsigned char* payload,int paylen,char *prefix); +int encode_content_type( + char *hdrstart, int hdrlen, unsigned int bodi, char *where); +int encode_accept(char *hdrstart, int hdrlen, unsigned int *bodi, char *where); +int encode_mime_type( + char *hdrstart, int hdrlen, unsigned int bodi, char *where); +int print_encoded_mime_type(FILE *fd, char *hdr, int hdrlen, + unsigned int *payload, int paylen, char *prefix); +int print_encoded_content_type(FILE *fd, char *hdr, int hdrlen, + unsigned char *payload, int paylen, char *prefix); +int print_encoded_accept(FILE *fd, char *hdr, int hdrlen, + unsigned char *payload, int paylen, char *prefix); #endif diff --git a/src/modules/seas/encode_cseq.c b/src/modules/seas/encode_cseq.c index 5f934e5110b..09e1f934f49 100644 --- a/src/modules/seas/encode_cseq.c +++ b/src/modules/seas/encode_cseq.c @@ -44,7 +44,7 @@ #include "../../core/parser/parse_cseq.h" #include "../../core/dprint.h" #include "../../core/ut.h" -#include "xaddress.h"/*for SLOG*/ +#include "xaddress.h" /*for SLOG*/ /* Encoder for CSeq header * Returns the length of the encoded structure in bytes @@ -55,91 +55,96 @@ * 2: HDR-based ptr to the method name + method length * */ -int encode_cseq(char *hdrstart,int hdrlen,struct cseq_body *body,unsigned char *where) +int encode_cseq(char *hdrstart, int hdrlen, struct cseq_body *body, + unsigned char *where) { - unsigned int cseqnum; - unsigned char i; + unsigned int cseqnum; + unsigned char i; - /*which is the first bit set to 1 ? if i==0, the first bit, + /*which is the first bit set to 1 ? if i==0, the first bit, * if i==31, the last, if i==32, none*/ - for(i=0;(!(body->method_id & (0x01<number,&cseqnum)<0){ - LM_ERR("str2int(cseq number)\n"); - return -1; - } - cseqnum=htonl(cseqnum); - memcpy(&where[1],&cseqnum,4);/*I use 4 because 3261 says CSEq num must be 32 bits long*/ - where[5]=(unsigned char)(body->number.s-hdrstart); - where[6]=(unsigned char)(body->number.len); - where[7]=(unsigned char)(body->method.s-hdrstart); - where[8]=(unsigned char)(body->method.len); - return 9; + for(i = 0; (!(body->method_id & (0x01 << i))) && i < 32; i++) + ; + if(i == 32) + i = 0; + else + i++; + where[0] = i; + if(str2int(&body->number, &cseqnum) < 0) { + LM_ERR("str2int(cseq number)\n"); + return -1; + } + cseqnum = htonl(cseqnum); + memcpy(&where[1], &cseqnum, + 4); /*I use 4 because 3261 says CSEq num must be 32 bits long*/ + where[5] = (unsigned char)(body->number.s - hdrstart); + where[6] = (unsigned char)(body->number.len); + where[7] = (unsigned char)(body->method.s - hdrstart); + where[8] = (unsigned char)(body->method.len); + return 9; } -int print_encoded_cseq(FILE *fd,char *hdr,int hdrlen,unsigned char* payload,int paylen,char *prefix) +int print_encoded_cseq(FILE *fd, char *hdr, int hdrlen, unsigned char *payload, + int paylen, char *prefix) { - unsigned int cseqnum; - char *what; - - memcpy(&cseqnum,&payload[1],4); - cseqnum=ntohl(cseqnum); - fprintf(fd,"%sCSEQ NUMBER=%d==%.*s\n",prefix,cseqnum,payload[6],&hdr[payload[5]]); - switch(payload[0]){ - case 0: - what="UNDEFINED"; - break; - case 1: - what="INVITE"; - break; - case 2: - what="CANCEL"; - break; - case 3: - what="ACK"; - break; - case 4: - what="BYE"; - break; - case 5: - what="INFO"; - break; - case 6: - what="OPTIONS"; - break; - case 7: - what="UPDATE"; - break; - case 8: - what="REGISTER"; - break; - case 9: - what="MESSAGE"; - break; - case 10: - what="SUBSCRIBE"; - break; - case 11: - what="NOTIFY"; - break; - case 12: - what="PRACK"; - break; - case 13: - what="REFER"; - break; - case 14: - what="OTHER"; - break; - default: - what="UNKNOWN?"; - break; - } - fprintf(fd,"%sCSEQ METHOD=%s==%.*s\n",prefix,what,payload[8],&hdr[payload[7]]); - return 1; + unsigned int cseqnum; + char *what; + memcpy(&cseqnum, &payload[1], 4); + cseqnum = ntohl(cseqnum); + fprintf(fd, "%sCSEQ NUMBER=%d==%.*s\n", prefix, cseqnum, payload[6], + &hdr[payload[5]]); + switch(payload[0]) { + case 0: + what = "UNDEFINED"; + break; + case 1: + what = "INVITE"; + break; + case 2: + what = "CANCEL"; + break; + case 3: + what = "ACK"; + break; + case 4: + what = "BYE"; + break; + case 5: + what = "INFO"; + break; + case 6: + what = "OPTIONS"; + break; + case 7: + what = "UPDATE"; + break; + case 8: + what = "REGISTER"; + break; + case 9: + what = "MESSAGE"; + break; + case 10: + what = "SUBSCRIBE"; + break; + case 11: + what = "NOTIFY"; + break; + case 12: + what = "PRACK"; + break; + case 13: + what = "REFER"; + break; + case 14: + what = "OTHER"; + break; + default: + what = "UNKNOWN?"; + break; + } + fprintf(fd, "%sCSEQ METHOD=%s==%.*s\n", prefix, what, payload[8], + &hdr[payload[7]]); + return 1; } diff --git a/src/modules/seas/encode_cseq.h b/src/modules/seas/encode_cseq.h index bcba4b864c9..c3b43143eea 100644 --- a/src/modules/seas/encode_cseq.h +++ b/src/modules/seas/encode_cseq.h @@ -22,6 +22,8 @@ #define __ENCODE_CSEQ_H__ #include "../../core/str.h" #include "../../core/parser/msg_parser.h" -int encode_cseq(char *hdrstart,int hdrlen,struct cseq_body *body,unsigned char *where); -int print_encoded_cseq(FILE* fd,char *hdr,int hdrlen,unsigned char* payload,int paylen,char *prefix); +int encode_cseq(char *hdrstart, int hdrlen, struct cseq_body *body, + unsigned char *where); +int print_encoded_cseq(FILE *fd, char *hdr, int hdrlen, unsigned char *payload, + int paylen, char *prefix); #endif diff --git a/src/modules/seas/encode_digest.c b/src/modules/seas/encode_digest.c index fa83c0f112e..d98a80ec550 100644 --- a/src/modules/seas/encode_digest.c +++ b/src/modules/seas/encode_digest.c @@ -47,16 +47,16 @@ #include "encode_header.h" #include "encode_uri.h" -#define HAS_NAME_F 0x01 -#define HAS_REALM_F 0x02 -#define HAS_NONCE_F 0x04 -#define HAS_URI_F 0x08 -#define HAS_RESPONSE_F 0x10 -#define HAS_ALG_F 0x20 -#define HAS_CNONCE_F 0x40 -#define HAS_OPAQUE_F 0x80 -#define HAS_QoP_F 0x01 -#define HAS_NC_F 0x02 +#define HAS_NAME_F 0x01 +#define HAS_REALM_F 0x02 +#define HAS_NONCE_F 0x04 +#define HAS_URI_F 0x08 +#define HAS_RESPONSE_F 0x10 +#define HAS_ALG_F 0x20 +#define HAS_CNONCE_F 0x40 +#define HAS_OPAQUE_F 0x80 +#define HAS_QoP_F 0x01 +#define HAS_NC_F 0x02 /* * encodes a digest header body. * encoding is: @@ -79,161 +79,180 @@ * byte telling how long is the URI structure, and then the encoded URI structure. */ -int encode_digest(char *hdrstart,int hdrlen,dig_cred_t *digest,unsigned char *where) +int encode_digest( + char *hdrstart, int hdrlen, dig_cred_t *digest, unsigned char *where) { - int i=2,j=0;/* 2*flags */ - unsigned char flags1=0,flags2=0; - struct sip_uri sipuri; + int i = 2, j = 0; /* 2*flags */ + unsigned char flags1 = 0, flags2 = 0; + struct sip_uri sipuri; - if(digest->username.whole.s && digest->username.whole.len){ - flags1|=HAS_NAME_F; - where[i++]=(unsigned char)(digest->username.whole.s-hdrstart); - where[i++]=(unsigned char)digest->username.whole.len; - } - if(digest->realm.s && digest->realm.len){ - flags1|=HAS_REALM_F; - where[i++]=(unsigned char)(digest->realm.s-hdrstart); - where[i++]=(unsigned char)digest->realm.len; - } - if(digest->nonce.s && digest->nonce.len){ - flags1|=HAS_NONCE_F; - where[i++]=(unsigned char)(digest->nonce.s-hdrstart); - where[i++]=(unsigned char)digest->nonce.len; - } - if(digest->uri.s && digest->uri.len){ - memset(&sipuri,0,sizeof(struct sip_uri)); - flags1|=HAS_URI_F; - if (parse_uri(digest->uri.s, digest->uri.len,&sipuri) < 0 ) { - LM_ERR("Bad URI in address\n"); - return -1; - }else{ - if((j=encode_uri2(hdrstart,hdrlen,digest->uri,&sipuri,&where[i+1]))<0){ - LM_ERR("Error encoding the URI\n"); - return -1; - }else{ - where[i]=(unsigned char)j; - i+=(j+1); - } - } - } - if(digest->response.s && digest->response.len){ - flags1|=HAS_RESPONSE_F; - where[i++]=(unsigned char)(digest->response.s-hdrstart); - where[i++]=(unsigned char)digest->response.len; - } - if(digest->alg.alg_str.s && digest->alg.alg_str.len){ - flags1|=HAS_ALG_F; - where[i++]=(unsigned char)(digest->alg.alg_str.s-hdrstart); - where[i++]=(unsigned char)digest->alg.alg_str.len; - } - if(digest->cnonce.s && digest->cnonce.len){ - flags1|=HAS_CNONCE_F; - where[i++]=(unsigned char)(digest->cnonce.s-hdrstart); - where[i++]=(unsigned char)digest->cnonce.len; - } - if(digest->opaque.s && digest->opaque.len){ - flags1|=HAS_OPAQUE_F; - where[i++]=(unsigned char)(digest->opaque.s-hdrstart); - where[i++]=(unsigned char)digest->opaque.len; - } - if(digest->qop.qop_str.s && digest->qop.qop_str.len){ - flags2|=HAS_QoP_F; - where[i++]=(unsigned char)(digest->qop.qop_str.s-hdrstart); - where[i++]=(unsigned char)digest->qop.qop_str.len; - } - if(digest->nc.s && digest->nc.len){ - flags2|=HAS_NC_F; - where[i++]=(unsigned char)(digest->nc.s-hdrstart); - where[i++]=(unsigned char)digest->nc.len; - } - where[0]=flags1; - where[1]=flags2; - return i; + if(digest->username.whole.s && digest->username.whole.len) { + flags1 |= HAS_NAME_F; + where[i++] = (unsigned char)(digest->username.whole.s - hdrstart); + where[i++] = (unsigned char)digest->username.whole.len; + } + if(digest->realm.s && digest->realm.len) { + flags1 |= HAS_REALM_F; + where[i++] = (unsigned char)(digest->realm.s - hdrstart); + where[i++] = (unsigned char)digest->realm.len; + } + if(digest->nonce.s && digest->nonce.len) { + flags1 |= HAS_NONCE_F; + where[i++] = (unsigned char)(digest->nonce.s - hdrstart); + where[i++] = (unsigned char)digest->nonce.len; + } + if(digest->uri.s && digest->uri.len) { + memset(&sipuri, 0, sizeof(struct sip_uri)); + flags1 |= HAS_URI_F; + if(parse_uri(digest->uri.s, digest->uri.len, &sipuri) < 0) { + LM_ERR("Bad URI in address\n"); + return -1; + } else { + if((j = encode_uri2( + hdrstart, hdrlen, digest->uri, &sipuri, &where[i + 1])) + < 0) { + LM_ERR("Error encoding the URI\n"); + return -1; + } else { + where[i] = (unsigned char)j; + i += (j + 1); + } + } + } + if(digest->response.s && digest->response.len) { + flags1 |= HAS_RESPONSE_F; + where[i++] = (unsigned char)(digest->response.s - hdrstart); + where[i++] = (unsigned char)digest->response.len; + } + if(digest->alg.alg_str.s && digest->alg.alg_str.len) { + flags1 |= HAS_ALG_F; + where[i++] = (unsigned char)(digest->alg.alg_str.s - hdrstart); + where[i++] = (unsigned char)digest->alg.alg_str.len; + } + if(digest->cnonce.s && digest->cnonce.len) { + flags1 |= HAS_CNONCE_F; + where[i++] = (unsigned char)(digest->cnonce.s - hdrstart); + where[i++] = (unsigned char)digest->cnonce.len; + } + if(digest->opaque.s && digest->opaque.len) { + flags1 |= HAS_OPAQUE_F; + where[i++] = (unsigned char)(digest->opaque.s - hdrstart); + where[i++] = (unsigned char)digest->opaque.len; + } + if(digest->qop.qop_str.s && digest->qop.qop_str.len) { + flags2 |= HAS_QoP_F; + where[i++] = (unsigned char)(digest->qop.qop_str.s - hdrstart); + where[i++] = (unsigned char)digest->qop.qop_str.len; + } + if(digest->nc.s && digest->nc.len) { + flags2 |= HAS_NC_F; + where[i++] = (unsigned char)(digest->nc.s - hdrstart); + where[i++] = (unsigned char)digest->nc.len; + } + where[0] = flags1; + where[1] = flags2; + return i; } -int print_encoded_digest(FILE *fd,char *hdr,int hdrlen,unsigned char* payload,int paylen,char *prefix) +int print_encoded_digest(FILE *fd, char *hdr, int hdrlen, + unsigned char *payload, int paylen, char *prefix) { - int i=2;/* flags + flags1 */ - unsigned char flags1,flags2; + int i = 2; /* flags + flags1 */ + unsigned char flags1, flags2; - flags1=payload[0]; - flags2=payload[1]; - fprintf(fd,"%s",prefix); - for(i=0;ival); - memcpy(where,&i,4); - where[4]=(unsigned char)(body->text.s-hdrstart); - where[5]=(unsigned char)(body->text.len); - return 6; + i = htonl(body->val); + memcpy(where, &i, 4); + where[4] = (unsigned char)(body->text.s - hdrstart); + where[5] = (unsigned char)(body->text.len); + return 6; } -int print_encoded_expires(FILE *fd,char *hdr,int hdrlen,unsigned char* payload,int paylen,char *prefix) +int print_encoded_expires(FILE *fd, char *hdr, int hdrlen, + unsigned char *payload, int paylen, char *prefix) { - int i; - memcpy(&i,payload,4); - i=ntohl(i); - fprintf(fd,"%sEXPIRES VALUE=%d==%.*s\n",prefix,i,payload[5],&hdr[payload[4]]); - return 1; + int i; + memcpy(&i, payload, 4); + i = ntohl(i); + fprintf(fd, "%sEXPIRES VALUE=%d==%.*s\n", prefix, i, payload[5], + &hdr[payload[4]]); + return 1; } - - diff --git a/src/modules/seas/encode_expires.h b/src/modules/seas/encode_expires.h index 225de74ad6a..31696ed0518 100644 --- a/src/modules/seas/encode_expires.h +++ b/src/modules/seas/encode_expires.h @@ -20,5 +20,7 @@ */ -int encode_expires(char *hdrstart,int hdrlen,exp_body_t *body,unsigned char *where); -int print_encoded_expires(FILE* fd,char *hdr,int hdrlen,unsigned char* payload,int paylen,char *prefix); +int encode_expires( + char *hdrstart, int hdrlen, exp_body_t *body, unsigned char *where); +int print_encoded_expires(FILE *fd, char *hdr, int hdrlen, + unsigned char *payload, int paylen, char *prefix); diff --git a/src/modules/seas/encode_header.c b/src/modules/seas/encode_header.c index c91ebf236ad..82e5898cbed 100644 --- a/src/modules/seas/encode_header.c +++ b/src/modules/seas/encode_header.c @@ -68,16 +68,16 @@ #include "encode_msg.h" #include "encode_header.h" -#define REL_PTR(a,b) ((unsigned char)(b-a)) +#define REL_PTR(a, b) ((unsigned char)(b - a)) #define MAX_CONTACT_LEN 50 #define MAX_XHDR_LEN 255 #define SEGREGATE 0x02 #define ONLY_URIS 0x01 #define HEADER_OFFSET_IDX 0 -#define HEADER_LEN_IDX (HEADER_OFFSET_IDX+2) -#define HEADER_NAME_LEN_IDX (HEADER_LEN_IDX+2) -#define HEADER_PAYLOAD_IDX (HEADER_NAME_LEN_IDX+1) +#define HEADER_LEN_IDX (HEADER_OFFSET_IDX + 2) +#define HEADER_NAME_LEN_IDX (HEADER_LEN_IDX + 2) +#define HEADER_PAYLOAD_IDX (HEADER_NAME_LEN_IDX + 1) /* * This function encodes an arbitrary header into a chunk of bytes, @@ -88,435 +88,485 @@ * 2: length of the header * 1: length of the header name */ -int encode_header(struct sip_msg *sipmsg,struct hdr_field *hdr,unsigned char *payload,int paylen) +int encode_header(struct sip_msg *sipmsg, struct hdr_field *hdr, + unsigned char *payload, int paylen) { - int len=0; - unsigned int integer,*methods=0; - char *hdrstart,*tmp; - unsigned short int ptr; - struct to_body *tobody=0; - struct via_body *viabody=0; - struct cseq_body *cseqbody=0; - char *msg,*myerror; - int mlen; + int len = 0; + unsigned int integer, *methods = 0; + char *hdrstart, *tmp; + unsigned short int ptr; + struct to_body *tobody = 0; + struct via_body *viabody = 0; + struct cseq_body *cseqbody = 0; + char *msg, *myerror; + int mlen; - msg=sipmsg->buf; - mlen=sipmsg->len; - hdrstart = hdr->name.s; - if(hdrstart-msg<0){ - LM_ERR("header(%.*s) does not belong to sip_msg(hdrstartname.len,hdr->name.s); - return -1; - } - ptr=htons((short int)(hdrstart-msg)); - if((hdrstart-msg)>mlen){ - LM_ERR("out of the sip_msg bounds (%d>%d)\n",ntohs(ptr),mlen); - return -1; - } - if(hdr->len>(1<<16)){ - LM_ERR("length of header too long\n"); - return -1; - } - memcpy(payload,&ptr,2); - ptr=htons((short int)(hdr->len)); - memcpy(payload+HEADER_LEN_IDX,&ptr,2); - payload[HEADER_NAME_LEN_IDX]=(unsigned char)hdr->name.len; - if(hdr->len>256){ - LM_INFO("header bigger than 256 bytes. Skipping express-encoding\n"); - return 4;/*2 for header offset + 2 for header length*/ - } - switch(hdr->type){ - case HDR_FROM_T: - case HDR_TO_T: - case HDR_REFER_TO_T: - case HDR_RPID_T: - if(!hdr->parsed){ - if((tobody=pkg_malloc(sizeof(struct to_body)))==0){ - myerror="Out of memory !!\n"; - goto error; - } - memset(tobody,0,sizeof(struct to_body)); - parse_to(hdr->body.s,hdr->body.s+hdr->body.len+1,tobody); - if (tobody->error == PARSE_ERROR) { - myerror="bad (REFER,TO,FROM,RPID) header\n"; - free_to(tobody); - return 5; - goto error; - } - hdr->parsed=(struct to_body*)tobody; - }else - tobody=(struct to_body*)hdr->parsed; - if((len=encode_to_body(hdr->name.s,hdr->len,tobody,payload+5))<0){ - myerror="parsing from or to header\n"; - goto error; - }else{ - return 5+len; - } - break; - case HDR_CONTACT_T: - if(!hdr->parsed) - if(parse_contact(hdr)<0){ - myerror="parsing contact\n"; - goto error; - } - if((len=encode_contact_body(hdr->name.s,hdr->len,(contact_body_t*)hdr->parsed,payload+5))<0){ - myerror="encoding contact header\n"; - goto error; - }else{ - return 5+len; - } - break; - case HDR_ROUTE_T: - case HDR_RECORDROUTE_T: - if(!hdr->parsed) - if(parse_rr(hdr)<0){ - myerror="encoding route or recordroute\n"; - goto error; - } - if((len=encode_route_body(hdr->name.s,hdr->len,(rr_t*)hdr->parsed,payload+5))<0){ - myerror="encoding route or recordroute header\n"; - goto error; - }else{ - return 5+len; - } - break; - case HDR_CONTENTLENGTH_T: - if(!hdr->parsed){ - tmp=parse_content_length(hdr->body.s,hdr->body.s+hdr->body.len+1,(int*)&integer); - if (tmp==0){ - myerror="bad content_length header\n"; - goto error; - } - hdr->parsed=(void*)(long)integer; - } - if((len=encode_contentlength(hdr->name.s,hdr->len,(long int)hdr->parsed,(char*)(payload+5)))<0){ - myerror="encoding content-length header\n"; - goto error; - }else{ - return 5+len; - } - break; - case HDR_VIA_T: - if(!hdr->parsed){ - if((viabody=pkg_malloc(sizeof(struct via_body)))==0){ - myerror="out of memory\n"; - goto error; - } - memset(viabody,0,sizeof(struct via_body)); - if(parse_via(hdr->body.s,hdr->body.s+hdr->body.len+1,viabody)==0){ - myerror="encoding via \n"; - goto error; - } - hdr->parsed=viabody; - } - if((len=encode_via_body(hdr->name.s,hdr->len,(struct via_body*)hdr->parsed,payload+5))<0){ - myerror="encoding via header\n"; - goto error; - }else{ - return 5+len; - } - break; - case HDR_ACCEPT_T: - if(!hdr->parsed){ - if(parse_accept_hdr(sipmsg)<0){ - return 5; - } - } - if((len=encode_accept(hdr->name.s,hdr->len,(unsigned int*)hdr->parsed,(char*)(payload+5)))<0){ - myerror="encoding via header\n"; - goto error; - }else{ - return 5+len; - } - break; - case HDR_CONTENTTYPE_T: - if(!hdr->parsed){ - if(parse_content_type_hdr(sipmsg)<0){ - myerror="encoding content-type header\n"; - goto error; - } - } - if((len=encode_content_type(hdr->name.s,hdr->len,(unsigned int)(long int)hdr->parsed,(char*)(payload+5)))<0){ - myerror="encoding via header\n"; - goto error; - }else{ - return 5+len; - } - break; - case HDR_CSEQ_T: - if(!hdr->parsed){ - if((cseqbody=pkg_malloc(sizeof(struct cseq_body)))==0){ - myerror="out of memory\n"; - goto error; - } - memset(cseqbody,0,sizeof(struct cseq_body)); - if(parse_cseq(hdr->name.s,hdr->body.s+hdr->body.len+1,cseqbody)==0){ - myerror="encoding cseq header\n"; - goto error; - } - hdr->parsed=cseqbody; - } - if((len=encode_cseq(hdr->name.s,hdr->len,(struct cseq_body*)hdr->parsed,payload+5))<0){ - myerror="encoding via header\n"; - goto error; - }else{ - return 5+len; - } - break; - case HDR_EXPIRES_T: - if(!hdr->parsed){ - if(parse_expires(hdr)<0){ - myerror="encoding expires header\n"; - goto error; - } - } - if((len=encode_expires(hdr->name.s,hdr->len,(exp_body_t *)hdr->parsed,payload+5))<0){ - myerror="encoding expires header\n"; - goto error; - }else{ - return 5+len; - } - break; - case HDR_ALLOW_T: - if(!hdr->parsed){ - if((methods=pkg_malloc(sizeof(unsigned int)))==0){ - myerror="out of memory\n"; - goto error; - } - *methods=0; - if(parse_methods(&hdr->body,methods)!=0){ - myerror="encoding allow header\n"; - pkg_free(methods); - return 5; - /*goto error;*/ - } - hdr->parsed=methods; - } - if((len=encode_allow(hdr->name.s,hdr->len,(unsigned int*)hdr->parsed,(char*)(payload+5)))<0){ - myerror="encoding allow header\n"; - goto error; - }else{ - return 5+len; - } - break; - case HDR_AUTHORIZATION_T: - case HDR_PROXYAUTH_T: - if(!hdr->parsed){ - if(parse_credentials(hdr)<0){ - myerror="encoding a digest header\n"; - goto error; - } - } - if((len=encode_digest(hdr->name.s,hdr->len,(dig_cred_t*)(&(((auth_body_t*)hdr->parsed)->digest)),payload+5))<0){ - myerror="encoding allow header\n"; - goto error; - }else{ - return 5+len; - } - break; - default: - return 5; - } - return 1; + msg = sipmsg->buf; + mlen = sipmsg->len; + hdrstart = hdr->name.s; + if(hdrstart - msg < 0) { + LM_ERR("header(%.*s) does not belong to sip_msg(hdrstartname.len, hdr->name.s); + return -1; + } + ptr = htons((short int)(hdrstart - msg)); + if((hdrstart - msg) > mlen) { + LM_ERR("out of the sip_msg bounds (%d>%d)\n", ntohs(ptr), mlen); + return -1; + } + if(hdr->len > (1 << 16)) { + LM_ERR("length of header too long\n"); + return -1; + } + memcpy(payload, &ptr, 2); + ptr = htons((short int)(hdr->len)); + memcpy(payload + HEADER_LEN_IDX, &ptr, 2); + payload[HEADER_NAME_LEN_IDX] = (unsigned char)hdr->name.len; + if(hdr->len > 256) { + LM_INFO("header bigger than 256 bytes. Skipping express-encoding\n"); + return 4; /*2 for header offset + 2 for header length*/ + } + switch(hdr->type) { + case HDR_FROM_T: + case HDR_TO_T: + case HDR_REFER_TO_T: + case HDR_RPID_T: + if(!hdr->parsed) { + if((tobody = pkg_malloc(sizeof(struct to_body))) == 0) { + myerror = "Out of memory !!\n"; + goto error; + } + memset(tobody, 0, sizeof(struct to_body)); + parse_to(hdr->body.s, hdr->body.s + hdr->body.len + 1, tobody); + if(tobody->error == PARSE_ERROR) { + myerror = "bad (REFER,TO,FROM,RPID) header\n"; + free_to(tobody); + return 5; + goto error; + } + hdr->parsed = (struct to_body *)tobody; + } else + tobody = (struct to_body *)hdr->parsed; + if((len = encode_to_body( + hdr->name.s, hdr->len, tobody, payload + 5)) + < 0) { + myerror = "parsing from or to header\n"; + goto error; + } else { + return 5 + len; + } + break; + case HDR_CONTACT_T: + if(!hdr->parsed) + if(parse_contact(hdr) < 0) { + myerror = "parsing contact\n"; + goto error; + } + if((len = encode_contact_body(hdr->name.s, hdr->len, + (contact_body_t *)hdr->parsed, payload + 5)) + < 0) { + myerror = "encoding contact header\n"; + goto error; + } else { + return 5 + len; + } + break; + case HDR_ROUTE_T: + case HDR_RECORDROUTE_T: + if(!hdr->parsed) + if(parse_rr(hdr) < 0) { + myerror = "encoding route or recordroute\n"; + goto error; + } + if((len = encode_route_body(hdr->name.s, hdr->len, + (rr_t *)hdr->parsed, payload + 5)) + < 0) { + myerror = "encoding route or recordroute header\n"; + goto error; + } else { + return 5 + len; + } + break; + case HDR_CONTENTLENGTH_T: + if(!hdr->parsed) { + tmp = parse_content_length(hdr->body.s, + hdr->body.s + hdr->body.len + 1, (int *)&integer); + if(tmp == 0) { + myerror = "bad content_length header\n"; + goto error; + } + hdr->parsed = (void *)(long)integer; + } + if((len = encode_contentlength(hdr->name.s, hdr->len, + (long int)hdr->parsed, (char *)(payload + 5))) + < 0) { + myerror = "encoding content-length header\n"; + goto error; + } else { + return 5 + len; + } + break; + case HDR_VIA_T: + if(!hdr->parsed) { + if((viabody = pkg_malloc(sizeof(struct via_body))) == 0) { + myerror = "out of memory\n"; + goto error; + } + memset(viabody, 0, sizeof(struct via_body)); + if(parse_via(hdr->body.s, hdr->body.s + hdr->body.len + 1, + viabody) + == 0) { + myerror = "encoding via \n"; + goto error; + } + hdr->parsed = viabody; + } + if((len = encode_via_body(hdr->name.s, hdr->len, + (struct via_body *)hdr->parsed, payload + 5)) + < 0) { + myerror = "encoding via header\n"; + goto error; + } else { + return 5 + len; + } + break; + case HDR_ACCEPT_T: + if(!hdr->parsed) { + if(parse_accept_hdr(sipmsg) < 0) { + return 5; + } + } + if((len = encode_accept(hdr->name.s, hdr->len, + (unsigned int *)hdr->parsed, (char *)(payload + 5))) + < 0) { + myerror = "encoding via header\n"; + goto error; + } else { + return 5 + len; + } + break; + case HDR_CONTENTTYPE_T: + if(!hdr->parsed) { + if(parse_content_type_hdr(sipmsg) < 0) { + myerror = "encoding content-type header\n"; + goto error; + } + } + if((len = encode_content_type(hdr->name.s, hdr->len, + (unsigned int)(long int)hdr->parsed, + (char *)(payload + 5))) + < 0) { + myerror = "encoding via header\n"; + goto error; + } else { + return 5 + len; + } + break; + case HDR_CSEQ_T: + if(!hdr->parsed) { + if((cseqbody = pkg_malloc(sizeof(struct cseq_body))) == 0) { + myerror = "out of memory\n"; + goto error; + } + memset(cseqbody, 0, sizeof(struct cseq_body)); + if(parse_cseq(hdr->name.s, hdr->body.s + hdr->body.len + 1, + cseqbody) + == 0) { + myerror = "encoding cseq header\n"; + goto error; + } + hdr->parsed = cseqbody; + } + if((len = encode_cseq(hdr->name.s, hdr->len, + (struct cseq_body *)hdr->parsed, payload + 5)) + < 0) { + myerror = "encoding via header\n"; + goto error; + } else { + return 5 + len; + } + break; + case HDR_EXPIRES_T: + if(!hdr->parsed) { + if(parse_expires(hdr) < 0) { + myerror = "encoding expires header\n"; + goto error; + } + } + if((len = encode_expires(hdr->name.s, hdr->len, + (exp_body_t *)hdr->parsed, payload + 5)) + < 0) { + myerror = "encoding expires header\n"; + goto error; + } else { + return 5 + len; + } + break; + case HDR_ALLOW_T: + if(!hdr->parsed) { + if((methods = pkg_malloc(sizeof(unsigned int))) == 0) { + myerror = "out of memory\n"; + goto error; + } + *methods = 0; + if(parse_methods(&hdr->body, methods) != 0) { + myerror = "encoding allow header\n"; + pkg_free(methods); + return 5; + /*goto error;*/ + } + hdr->parsed = methods; + } + if((len = encode_allow(hdr->name.s, hdr->len, + (unsigned int *)hdr->parsed, (char *)(payload + 5))) + < 0) { + myerror = "encoding allow header\n"; + goto error; + } else { + return 5 + len; + } + break; + case HDR_AUTHORIZATION_T: + case HDR_PROXYAUTH_T: + if(!hdr->parsed) { + if(parse_credentials(hdr) < 0) { + myerror = "encoding a digest header\n"; + goto error; + } + } + if((len = encode_digest(hdr->name.s, hdr->len, + (dig_cred_t *)(&(((auth_body_t *)hdr->parsed)->digest)), + payload + 5)) + < 0) { + myerror = "encoding allow header\n"; + goto error; + } else { + return 5 + len; + } + break; + default: + return 5; + } + return 1; error: - if(tobody) - pkg_free(tobody); - if(cseqbody) - pkg_free(cseqbody); - if(viabody) - free_via_list(viabody); - if(methods) - pkg_free(methods); - LM_ERR("%s",myerror); - return -1; + if(tobody) + pkg_free(tobody); + if(cseqbody) + pkg_free(cseqbody); + if(viabody) + free_via_list(viabody); + if(methods) + pkg_free(methods); + LM_ERR("%s", myerror); + return -1; } -int print_encoded_header(FILE *fd,char *msg,int msglen,unsigned char *payload,int len,char type,char *prefix) +int print_encoded_header(FILE *fd, char *msg, int msglen, + unsigned char *payload, int len, char type, char *prefix) { - char *hdr_start_ptr; - short int start_idx,i; + char *hdr_start_ptr; + short int start_idx, i; - memcpy(&start_idx,payload,2); - start_idx=ntohs(start_idx); + memcpy(&start_idx, payload, 2); + start_idx = ntohs(start_idx); - hdr_start_ptr = &msg[start_idx]; - memcpy(&i,payload+HEADER_LEN_IDX,2); - i=ntohs(i); + hdr_start_ptr = &msg[start_idx]; + memcpy(&i, payload + HEADER_LEN_IDX, 2); + i = ntohs(i); - fprintf(fd,"%sHEADER NAME:[%.*s]\n",prefix,payload[HEADER_NAME_LEN_IDX],hdr_start_ptr); - fprintf(fd,"%sHEADER:[%.*s]\n",prefix,i-2,hdr_start_ptr); - fprintf(fd,"%sHEADER CODE=",prefix); - for(i=0;itype){ - case HDR_CALLID_T: - return 'i'; - case HDR_CONTACT_T: - return 'm'; - case HDR_CONTENTLENGTH_T: - return 'l'; - case HDR_CONTENTTYPE_T: - return 'c'; - case HDR_FROM_T: - return 'f'; - case HDR_SUBJECT_T: - return 's'; - case HDR_SUPPORTED_T: - return 'k'; - case HDR_TO_T: - return 't'; - case HDR_VIA_T: - return 'v'; - case HDR_ROUTE_T: - return 'r'; - case HDR_RECORDROUTE_T: - return 'R'; - case HDR_ALLOW_T: - return 'a'; - case HDR_ACCEPT_T: - return 'A'; - case HDR_CSEQ_T: - return 'S'; - case HDR_REFER_TO_T: - return 'o'; - case HDR_RPID_T: - return 'p'; - case HDR_EXPIRES_T: - return 'P'; - case HDR_AUTHORIZATION_T: - return 'H'; - case HDR_PROXYAUTH_T: - return 'z'; - default: - return 'x'; - } - return 'x'; + switch(hf->type) { + case HDR_CALLID_T: + return 'i'; + case HDR_CONTACT_T: + return 'm'; + case HDR_CONTENTLENGTH_T: + return 'l'; + case HDR_CONTENTTYPE_T: + return 'c'; + case HDR_FROM_T: + return 'f'; + case HDR_SUBJECT_T: + return 's'; + case HDR_SUPPORTED_T: + return 'k'; + case HDR_TO_T: + return 't'; + case HDR_VIA_T: + return 'v'; + case HDR_ROUTE_T: + return 'r'; + case HDR_RECORDROUTE_T: + return 'R'; + case HDR_ALLOW_T: + return 'a'; + case HDR_ACCEPT_T: + return 'A'; + case HDR_CSEQ_T: + return 'S'; + case HDR_REFER_TO_T: + return 'o'; + case HDR_RPID_T: + return 'p'; + case HDR_EXPIRES_T: + return 'P'; + case HDR_AUTHORIZATION_T: + return 'H'; + case HDR_PROXYAUTH_T: + return 'z'; + default: + return 'x'; + } + return 'x'; } /* This function extracts meta-info from the sip_msg structure and @@ -146,215 +147,221 @@ char get_header_code(struct hdr_field *hf) * TODO: msg->parsed_uri msg->parsed_orig_uri_ok, msg->first_line->u.request.uri * buggy and little bit fuzzy */ -int encode_msg(struct sip_msg *msg,char *payload,int len) +int encode_msg(struct sip_msg *msg, char *payload, int len) { - int i,j=0,k,u,request; - unsigned short int h; - struct hdr_field* hf; - struct msg_start* ms; - struct sip_uri miuri; - char *myerror=NULL; - ptrdiff_t diff; + int i, j = 0, k, u, request; + unsigned short int h; + struct hdr_field *hf; + struct msg_start *ms; + struct sip_uri miuri; + char *myerror = NULL; + ptrdiff_t diff; - if(len < MAX_ENCODED_MSG + MAX_MESSAGE_LEN) - return -1; + if(len < MAX_ENCODED_MSG + MAX_MESSAGE_LEN) + return -1; - if(parse_headers(msg,HDR_EOH_F,0)<0){ - myerror="in parse_headers"; - goto error; - } - memset(payload,0,len); - ms=&msg->first_line; + if(parse_headers(msg, HDR_EOH_F, 0) < 0) { + myerror = "in parse_headers"; + goto error; + } + memset(payload, 0, len); + ms = &msg->first_line; if(ms->type == SIP_REQUEST) - request=1; + request = 1; else if(ms->type == SIP_REPLY) - request=0; - else{ - myerror="message is neither request nor response"; + request = 0; + else { + myerror = "message is neither request nor response"; goto error; } if(request) { - for(h=0;h<32;j=(0x01<u.request.method_value) break; } else { - h=(unsigned short)(ms->u.reply.statuscode); + h = (unsigned short)(ms->u.reply.statuscode); } - if(h==32){/*statuscode won't be 32...*/ - myerror="unknown message type\n"; - goto error; - } - h=htons(h); - /*first goes the message code type*/ - memcpy(payload,&h,2); - h=htons((unsigned short int)msg->len); - /*then goes the message start idx, but we'll put it later*/ - /*then goes the message length (we hope it to be less than 65535 bytes...)*/ - memcpy(&payload[MSG_LEN_IDX],&h,2); - /*then goes the content start index (starting from SIP MSG START)*/ - if(0>(diff=(get_body(msg)-(msg->buf)))){ - myerror="body starts before the message (uh ?)"; - goto error; - }else - h=htons((unsigned short int)diff); - memcpy(payload+CONTENT_IDX,&h,2); - payload[METHOD_CODE_IDX]=(unsigned char)(request? - (ms->u.request.method.s-msg->buf): - (ms->u.reply.status.s-msg->buf)); - payload[METHOD_CODE_IDX+1]=(unsigned char)(request? - (ms->u.request.method.len): - (ms->u.reply.status.len)); - payload[URI_REASON_IDX]=(unsigned char)(request? - (ms->u.request.uri.s-msg->buf): - (ms->u.reply.reason.s-msg->buf)); - payload[URI_REASON_IDX+1]=(unsigned char)(request? - (ms->u.request.uri.len): - (ms->u.reply.reason.len)); - payload[VERSION_IDX]=(unsigned char)(request? - (ms->u.request.version.s-msg->buf): - (ms->u.reply.version.s-msg->buf)); - if(request){ - if (parse_uri(ms->u.request.uri.s,ms->u.request.uri.len, &miuri)<0){ - LM_ERR("<%.*s>\n",ms->u.request.uri.len,ms->u.request.uri.s); - myerror="while parsing the R-URI"; - goto error; - } - if(0>(j=encode_uri2(msg->buf, - ms->u.request.method.s-msg->buf+ms->len, - ms->u.request.uri,&miuri, - (unsigned char*)&payload[REQUEST_URI_IDX+1]))) - { - myerror="ENCODE_MSG: ERROR while encoding the R-URI"; - goto error; - } - payload[REQUEST_URI_IDX]=(unsigned char)j; - k=REQUEST_URI_IDX+1+j; - }else - k=REQUEST_URI_IDX; - u=k; - k++; - for(i=0,hf=msg->headers;hf;hf=hf->next,i++); - i++;/*we do as if there was an extra header, that marks the end of + if(h == 32) { /*statuscode won't be 32...*/ + myerror = "unknown message type\n"; + goto error; + } + h = htons(h); + /*first goes the message code type*/ + memcpy(payload, &h, 2); + h = htons((unsigned short int)msg->len); + /*then goes the message start idx, but we'll put it later*/ + /*then goes the message length (we hope it to be less than 65535 bytes...)*/ + memcpy(&payload[MSG_LEN_IDX], &h, 2); + /*then goes the content start index (starting from SIP MSG START)*/ + if(0 > (diff = (get_body(msg) - (msg->buf)))) { + myerror = "body starts before the message (uh ?)"; + goto error; + } else + h = htons((unsigned short int)diff); + memcpy(payload + CONTENT_IDX, &h, 2); + payload[METHOD_CODE_IDX] = + (unsigned char)(request ? (ms->u.request.method.s - msg->buf) + : (ms->u.reply.status.s - msg->buf)); + payload[METHOD_CODE_IDX + 1] = + (unsigned char)(request ? (ms->u.request.method.len) + : (ms->u.reply.status.len)); + payload[URI_REASON_IDX] = + (unsigned char)(request ? (ms->u.request.uri.s - msg->buf) + : (ms->u.reply.reason.s - msg->buf)); + payload[URI_REASON_IDX + 1] = + (unsigned char)(request ? (ms->u.request.uri.len) + : (ms->u.reply.reason.len)); + payload[VERSION_IDX] = + (unsigned char)(request ? (ms->u.request.version.s - msg->buf) + : (ms->u.reply.version.s - msg->buf)); + if(request) { + if(parse_uri(ms->u.request.uri.s, ms->u.request.uri.len, &miuri) < 0) { + LM_ERR("<%.*s>\n", ms->u.request.uri.len, ms->u.request.uri.s); + myerror = "while parsing the R-URI"; + goto error; + } + if(0 > (j = encode_uri2(msg->buf, + ms->u.request.method.s - msg->buf + ms->len, + ms->u.request.uri, &miuri, + (unsigned char *)&payload[REQUEST_URI_IDX + 1]))) { + myerror = "ENCODE_MSG: ERROR while encoding the R-URI"; + goto error; + } + payload[REQUEST_URI_IDX] = (unsigned char)j; + k = REQUEST_URI_IDX + 1 + j; + } else + k = REQUEST_URI_IDX; + u = k; + k++; + for(i = 0, hf = msg->headers; hf; hf = hf->next, i++) + ; + i++; /*we do as if there was an extra header, that marks the end of the previous header in the headers hashtable(read below)*/ - j=k+3*i; - for(i=0,hf=msg->headers;hf;hf=hf->next,k+=3){ - payload[k]=(unsigned char)(hf->type & 0xFF); - h=htons(j); - /*now goes a payload-based-ptr to where the header-code starts*/ - memcpy(&payload[k+1],&h,2); - /*TODO fix this... fixed with k-=3?*/ - if(0>(i=encode_header(msg,hf,(unsigned char*)(payload+j),MAX_ENCODED_MSG+MAX_MESSAGE_LEN-j))){ - LM_ERR("encoding header %.*s\n",hf->name.len,hf->name.s); - goto error; - k-=3; - continue; - } - j+=(unsigned short int)i; - } - /*now goes the number of headers that have been found, right after the meta-msg-section*/ - payload[u]=(unsigned char)((k-u-1)/3); - j=htons(j); - /*now copy the number of bytes that the headers-meta-section has occupied,right afther + j = k + 3 * i; + for(i = 0, hf = msg->headers; hf; hf = hf->next, k += 3) { + payload[k] = (unsigned char)(hf->type & 0xFF); + h = htons(j); + /*now goes a payload-based-ptr to where the header-code starts*/ + memcpy(&payload[k + 1], &h, 2); + /*TODO fix this... fixed with k-=3?*/ + if(0 > (i = encode_header(msg, hf, (unsigned char *)(payload + j), + MAX_ENCODED_MSG + MAX_MESSAGE_LEN - j))) { + LM_ERR("encoding header %.*s\n", hf->name.len, hf->name.s); + goto error; + k -= 3; + continue; + } + j += (unsigned short int)i; + } + /*now goes the number of headers that have been found, right after the meta-msg-section*/ + payload[u] = (unsigned char)((k - u - 1) / 3); + j = htons(j); + /*now copy the number of bytes that the headers-meta-section has occupied,right afther * headers-meta-section(the array with ['v',[2:where],'r',[2:where],'R',[2:where],...] * this is to know where the LAST header ends, since the length of each header-struct * is calculated substracting the nextHeaderStart - presentHeaderStart * the k+1 is because payload[k] is usually the letter*/ - memcpy(&payload[k+1],&j,2); - k+=3; - j=ntohs(j); - /*now we copy the headers-meta-section after the msg-headers-meta-section*/ - /*memcpy(&payload[k],payload2,j);*/ - /*j+=k;*/ - /*pkg_free(payload2);*/ - /*now we copy the actual message after the headers-meta-section*/ + memcpy(&payload[k + 1], &j, 2); + k += 3; + j = ntohs(j); + /*now we copy the headers-meta-section after the msg-headers-meta-section*/ + /*memcpy(&payload[k],payload2,j);*/ + /*j+=k;*/ + /*pkg_free(payload2);*/ + /*now we copy the actual message after the headers-meta-section*/ if(len < j + msg->len + 1) { - LM_ERR("not enough space to encode sip message\n"); - return -1; + LM_ERR("not enough space to encode sip message\n"); + return -1; } - memcpy(&payload[j],msg->buf,msg->len); - LM_DBG("msglen = %d,msg starts at %d\n",msg->len,j); - j=htons(j); - /*now we copy at the beginning, the index to where the actual message starts*/ - memcpy(&payload[MSG_START_IDX],&j,2); - return GET_PAY_SIZE( payload ); + memcpy(&payload[j], msg->buf, msg->len); + LM_DBG("msglen = %d,msg starts at %d\n", msg->len, j); + j = htons(j); + /*now we copy at the beginning, the index to where the actual message starts*/ + memcpy(&payload[MSG_START_IDX], &j, 2); + return GET_PAY_SIZE(payload); error: - LM_ERR("%s\n",myerror); - return -1; + LM_ERR("%s\n", myerror); + return -1; } -int decode_msg(struct sip_msg *msg,char *code, unsigned int len) +int decode_msg(struct sip_msg *msg, char *code, unsigned int len) { - unsigned short int h; - char *myerror=NULL; + unsigned short int h; + char *myerror = NULL; - memcpy(&h,&code[2],2); - h=ntohs(h); - /*TODO use shortcuts in meta-info header.*/ + memcpy(&h, &code[2], 2); + h = ntohs(h); + /*TODO use shortcuts in meta-info header.*/ - msg->buf=&code[h]; - memcpy(&h,&code[4],2); - h=ntohs(h); - msg->len=h; - if(parse_headers(msg,HDR_EOH_F,0)<0){ - myerror="in parse_headers"; - goto error; - } + msg->buf = &code[h]; + memcpy(&h, &code[4], 2); + h = ntohs(h); + msg->len = h; + if(parse_headers(msg, HDR_EOH_F, 0) < 0) { + myerror = "in parse_headers"; + goto error; + } error: - LM_ERR("(%s)\n",myerror); - return -1; + LM_ERR("(%s)\n", myerror); + return -1; } -int print_encoded_msg(FILE* fd,char *code,char *prefix) +int print_encoded_msg(FILE *fd, char *code, char *prefix) { - unsigned short int i,j,k,l,m,msglen; - char r,*msg; - unsigned char *payload; - - payload=(unsigned char*)code; - memcpy(&i,code,2); - memcpy(&j,&code[MSG_START_IDX],2); - memcpy(&msglen,&code[MSG_LEN_IDX],2); - i=ntohs(i); - j=ntohs(j); - msglen=ntohs(msglen); - for(k=0;knext){ - where[i++]=(unsigned char)(toparam->name.s-hdrstart); - if(toparam->value.s) - mylittlepointer=toparam->value.s; - else - if(toparam->next) - mylittlepointer=toparam->next->name.s; - else - mylittlepointer=toparam->name.s+toparam->name.len+1; - if(mylittlepointer[-1]=='\"')/*check if the parameter was quoted*/ - mylittlepointer--;/*if so, account for quotes*/ - where[i++]=(unsigned char)(mylittlepointer-hdrstart); - } - if((toparam=tbody->last_param)){ - if(toparam->value.s) - mylittlepointer=toparam->value.s+toparam->value.len; - else - mylittlepointer=toparam->name.s+toparam->name.len; - if(mylittlepointer[0]=='\"')/*check if the parameter was quoted*/ - mylittlepointer++;/*if so, account for quotes*/ - where[i++]=(unsigned char)(mylittlepointer-hdrstart+1); - } - return i; - }else if(to=='n'){ - params=(struct param*)pars; - for(parametro=reverseParameters(params);parametro;parametro=parametro->next){ - where[i++]=(unsigned char)(parametro->name.s-hdrstart); - if(parametro->body.s) - mylittlepointer=parametro->body.s; - else - if(parametro->next) - mylittlepointer=parametro->next->name.s; - else - mylittlepointer=parametro->name.s+parametro->name.len+1; - if(mylittlepointer[-1]=='\"')/*check if the parameter was quoted*/ - mylittlepointer--;/*if so, account for quotes*/ - where[i++]=(unsigned char)(mylittlepointer-hdrstart); - } - /*look for the last parameter*/ - /*WARNING the ** parameters are in reversed order !!! */ - /*TODO parameter encoding logic should be moved to a specific function...*/ - for(parametro=params;parametro && parametro->next;parametro=parametro->next); - /*printf("PARAMETRO:%.*s\n",parametro->name.len,parametro->name.s);*/ - if(parametro){ - if(parametro->body.s) - mylittlepointer=parametro->body.s+parametro->body.len; - else - mylittlepointer=parametro->name.s+parametro->name.len; - if(mylittlepointer[0]=='\"')/*check if the parameter was quoted*/ - mylittlepointer++;/*if so, account for quotes*/ - where[i++]=(unsigned char)(mylittlepointer-hdrstart+1); - } - return i; - }else if(to=='d'){ - dparams=(struct disposition_param*)pars; - for(dparam=dparams;dparam;dparam=dparam->next){ - where[i++]=(unsigned char)(dparam->name.s-hdrstart); - if(dparam->body.s) - mylittlepointer=dparam->body.s; - else - if(dparam->next) - mylittlepointer=dparam->next->name.s; - else - mylittlepointer=dparam->name.s+dparam->name.len+1; - if(mylittlepointer[-1]=='\"')/*check if the parameter was quoted*/ - mylittlepointer--;/*if so, account for quotes*/ - where[i++]=(unsigned char)(mylittlepointer-hdrstart); - } - /*WARNING the ** parameters are in reversed order !!! */ - /*TODO parameter encoding logic should be moved to a specific function...*/ - for(dparam=dparams;dparam && dparam->next;dparam=dparam->next); - if(dparam){ - if(dparam->body.s) - mylittlepointer=dparam->body.s+dparam->body.len; - else - mylittlepointer=dparam->name.s+dparam->name.len; - if(mylittlepointer[0]=='\"')/*check if the parameter was quoted*/ - mylittlepointer++;/*if so, account for quotes*/ - where[i++]=(unsigned char)(mylittlepointer-hdrstart+1); - } - return i; - }else if(to=='v'){ - vparams=(struct via_param*)pars; - vbody=(struct via_body*)_body; - for(vparam=vparams;vparam;vparam=vparam->next){ - where[i++]=REL_PTR(hdrstart,vparam->name.s); - if(vparam->value.s) - mylittlepointer=vparam->value.s; - else - if(vparam->next) - mylittlepointer=vparam->next->name.s; - else - mylittlepointer=vparam->name.s+vparam->name.len+1; - if(mylittlepointer[-1]=='\"')/*check if the parameter was quoted*/ - mylittlepointer--;/*if so, account for quotes*/ - where[i++]=REL_PTR(hdrstart,mylittlepointer); - } - if((vparam=vbody->last_param)){ - if(vparam->value.s) - mylittlepointer=vparam->value.s+vparam->value.len; - else - mylittlepointer=vparam->name.s+vparam->name.len; - if(mylittlepointer[0]=='\"')/*check if the parameter was quoted*/ - mylittlepointer++;/*if so, account for quotes*/ - where[i++]=REL_PTR(hdrstart,mylittlepointer+1); - } - return i; - }else if(to=='u'){ - paramlen=*((int*)_body); - paramstart=(char *)pars; - j=i=0; - if(paramstart==0 || paramlen==0) - return 0; - /*the first parameter start index, I suppose paramstart points to the first + struct param *parametro, *params; + struct to_param *toparam, *toparams; + struct disposition_param *dparam, *dparams; + struct via_param *vparam, *vparams; + struct via_body *vbody; + struct to_body *tbody; + char *mylittlepointer, *paramstart; + int i, j, paramlen; + i = 0; + if(!pars) + return 0; + if(to == 't') { + toparams = (struct to_param *)pars; + tbody = (struct to_body *)_body; + for(toparam = toparams; toparam; toparam = toparam->next) { + where[i++] = (unsigned char)(toparam->name.s - hdrstart); + if(toparam->value.s) + mylittlepointer = toparam->value.s; + else if(toparam->next) + mylittlepointer = toparam->next->name.s; + else + mylittlepointer = toparam->name.s + toparam->name.len + 1; + if(mylittlepointer[-1] + == '\"') /*check if the parameter was quoted*/ + mylittlepointer--; /*if so, account for quotes*/ + where[i++] = (unsigned char)(mylittlepointer - hdrstart); + } + if((toparam = tbody->last_param)) { + if(toparam->value.s) + mylittlepointer = toparam->value.s + toparam->value.len; + else + mylittlepointer = toparam->name.s + toparam->name.len; + if(mylittlepointer[0] == '\"') /*check if the parameter was quoted*/ + mylittlepointer++; /*if so, account for quotes*/ + where[i++] = (unsigned char)(mylittlepointer - hdrstart + 1); + } + return i; + } else if(to == 'n') { + params = (struct param *)pars; + for(parametro = reverseParameters(params); parametro; + parametro = parametro->next) { + where[i++] = (unsigned char)(parametro->name.s - hdrstart); + if(parametro->body.s) + mylittlepointer = parametro->body.s; + else if(parametro->next) + mylittlepointer = parametro->next->name.s; + else + mylittlepointer = parametro->name.s + parametro->name.len + 1; + if(mylittlepointer[-1] + == '\"') /*check if the parameter was quoted*/ + mylittlepointer--; /*if so, account for quotes*/ + where[i++] = (unsigned char)(mylittlepointer - hdrstart); + } + /*look for the last parameter*/ + /*WARNING the ** parameters are in reversed order !!! */ + /*TODO parameter encoding logic should be moved to a specific function...*/ + for(parametro = params; parametro && parametro->next; + parametro = parametro->next) + ; + /*printf("PARAMETRO:%.*s\n",parametro->name.len,parametro->name.s);*/ + if(parametro) { + if(parametro->body.s) + mylittlepointer = parametro->body.s + parametro->body.len; + else + mylittlepointer = parametro->name.s + parametro->name.len; + if(mylittlepointer[0] == '\"') /*check if the parameter was quoted*/ + mylittlepointer++; /*if so, account for quotes*/ + where[i++] = (unsigned char)(mylittlepointer - hdrstart + 1); + } + return i; + } else if(to == 'd') { + dparams = (struct disposition_param *)pars; + for(dparam = dparams; dparam; dparam = dparam->next) { + where[i++] = (unsigned char)(dparam->name.s - hdrstart); + if(dparam->body.s) + mylittlepointer = dparam->body.s; + else if(dparam->next) + mylittlepointer = dparam->next->name.s; + else + mylittlepointer = dparam->name.s + dparam->name.len + 1; + if(mylittlepointer[-1] + == '\"') /*check if the parameter was quoted*/ + mylittlepointer--; /*if so, account for quotes*/ + where[i++] = (unsigned char)(mylittlepointer - hdrstart); + } + /*WARNING the ** parameters are in reversed order !!! */ + /*TODO parameter encoding logic should be moved to a specific function...*/ + for(dparam = dparams; dparam && dparam->next; dparam = dparam->next) + ; + if(dparam) { + if(dparam->body.s) + mylittlepointer = dparam->body.s + dparam->body.len; + else + mylittlepointer = dparam->name.s + dparam->name.len; + if(mylittlepointer[0] == '\"') /*check if the parameter was quoted*/ + mylittlepointer++; /*if so, account for quotes*/ + where[i++] = (unsigned char)(mylittlepointer - hdrstart + 1); + } + return i; + } else if(to == 'v') { + vparams = (struct via_param *)pars; + vbody = (struct via_body *)_body; + for(vparam = vparams; vparam; vparam = vparam->next) { + where[i++] = REL_PTR(hdrstart, vparam->name.s); + if(vparam->value.s) + mylittlepointer = vparam->value.s; + else if(vparam->next) + mylittlepointer = vparam->next->name.s; + else + mylittlepointer = vparam->name.s + vparam->name.len + 1; + if(mylittlepointer[-1] + == '\"') /*check if the parameter was quoted*/ + mylittlepointer--; /*if so, account for quotes*/ + where[i++] = REL_PTR(hdrstart, mylittlepointer); + } + if((vparam = vbody->last_param)) { + if(vparam->value.s) + mylittlepointer = vparam->value.s + vparam->value.len; + else + mylittlepointer = vparam->name.s + vparam->name.len; + if(mylittlepointer[0] == '\"') /*check if the parameter was quoted*/ + mylittlepointer++; /*if so, account for quotes*/ + where[i++] = REL_PTR(hdrstart, mylittlepointer + 1); + } + return i; + } else if(to == 'u') { + paramlen = *((int *)_body); + paramstart = (char *)pars; + j = i = 0; + if(paramstart == 0 || paramlen == 0) + return 0; + /*the first parameter start index, I suppose paramstart points to the first letter of the first parameter: sip:elias@voztele.com;param1=true;param2=false paramstart points to __^ each parameter is codified with its {param_name_start_idx,[param_value_start_idx|next_param_start_idx]} */ - where[j++]=paramstart-hdrstart; - while(inameaddr.name.s && body->nameaddr.name.len) { + flags |= HAS_NAME_F; + where[i++] = (unsigned char)(body->nameaddr.name.s - hdrstart); + where[i++] = (unsigned char)body->nameaddr.name.len; + } + + if(parse_uri(body->nameaddr.uri.s, body->nameaddr.uri.len, &puri) < 0) { + LM_ERR("Bad URI in address\n"); + return -1; + } else { + if((j = encode_uri2( + hdrstart, hdrlen, body->nameaddr.uri, &puri, &where[i])) + < 0) { + LM_ERR("error codifying the URI\n"); + return -1; + } else { + i += j; + } + } + where[0] = flags; + where[1] = (unsigned char)j; + i += encode_parameters( + &where[i], (void *)body->params, hdrstart, body, 'n'); + return i; } -int print_encoded_route_body(FILE *fd,char *hdr,int hdrlen,unsigned char *payload,int paylen,char *prefix) +int print_encoded_route_body(FILE *fd, char *hdr, int hdrlen, + unsigned char *payload, int paylen, char *prefix) { - unsigned char numroutes; - int i,offset; - - fprintf(fd,"%s",prefix); - for(i=0;idisplay.s && body->display.len){ - flags|=HAS_DISPLAY_F; - if(body->display.s[0]=='\"'){ - body->display.s++; - body->display.len-=2; - } - where[i++]=(unsigned char)(body->display.s-hdrstart); - where[i++]=(unsigned char)(body->display.len); - } - if(body->tag_value.s && body->tag_value.len){ - flags|=HAS_TAG_F; - where[i++]=(unsigned char)(body->tag_value.s-hdrstart); - where[i++]=(unsigned char)body->tag_value.len; - } - if (parse_uri(body->uri.s, body->uri.len,&puri) < 0 ) { - LM_ERR("Bad URI in address\n"); - return -1; - }else{ - if((j=encode_uri2(hdrstart,hdrlen,body->uri,&puri,&where[i]))<0){ - LM_ERR("failed to codify the URI\n"); - return -1; - }else{ - i+=j; - } - } - where[0]=flags; - where[1]=(unsigned char)j; - i+=encode_parameters(&where[i],(void *)body->param_lst,hdrstart,body,'t'); + if(body->display.s && body->display.len) { + flags |= HAS_DISPLAY_F; + if(body->display.s[0] == '\"') { + body->display.s++; + body->display.len -= 2; + } + where[i++] = (unsigned char)(body->display.s - hdrstart); + where[i++] = (unsigned char)(body->display.len); + } + if(body->tag_value.s && body->tag_value.len) { + flags |= HAS_TAG_F; + where[i++] = (unsigned char)(body->tag_value.s - hdrstart); + where[i++] = (unsigned char)body->tag_value.len; + } + if(parse_uri(body->uri.s, body->uri.len, &puri) < 0) { + LM_ERR("Bad URI in address\n"); + return -1; + } else { + if((j = encode_uri2(hdrstart, hdrlen, body->uri, &puri, &where[i])) + < 0) { + LM_ERR("failed to codify the URI\n"); + return -1; + } else { + i += j; + } + } + where[0] = flags; + where[1] = (unsigned char)j; + i += encode_parameters( + &where[i], (void *)body->param_lst, hdrstart, body, 't'); - return i; + return i; } -int print_encoded_to_body(FILE *fd,char *hdr,int hdrlen,unsigned char* payload,int paylen,char *prefix) +int print_encoded_to_body(FILE *fd, char *hdr, int hdrlen, + unsigned char *payload, int paylen, char *prefix) { - int i=2;/* flags + urilength */ - unsigned char flags=0; + int i = 2; /* flags + urilength */ + unsigned char flags = 0; - flags=payload[0]; - fprintf(fd,"%s",prefix); - for(i=0;i255 || uriptr>hdrlen){ - LM_ERR("uri too long, or out of the sip_msg bounds\n"); - return -1; - } - payload[0]=uriptr; - payload[1]=(unsigned char)uri_str.len; - if(uri_parsed->user.s && uri_parsed->user.len){ - flags1 |= USER_F; - payload[i++]=REL_PTR(uri_str.s,uri_parsed->user.s); - } - if(uri_parsed->passwd.s && uri_parsed->passwd.len){ - flags1 |= PASSWORD_F; - payload[i++]=REL_PTR(uri_str.s,uri_parsed->passwd.s); - } - if(uri_parsed->host.s && uri_parsed->host.len){ - flags1 |= HOST_F; - payload[i++]=REL_PTR(uri_str.s,uri_parsed->host.s); - } - if(uri_parsed->port.s && uri_parsed->port.len){ - flags1 |= PORT_F; - payload[i++]=REL_PTR(uri_str.s,uri_parsed->port.s); - } - if(uri_parsed->params.s && uri_parsed->params.len){ - flags1 |= PARAMETERS_F; - payload[i++]=REL_PTR(uri_str.s,uri_parsed->params.s); - } - if(uri_parsed->headers.s && uri_parsed->headers.len){ - flags1 |= HEADERS_F; - payload[i++]=REL_PTR(uri_str.s,uri_parsed->headers.s); - } - payload[i]=(unsigned char)(uri_str.len+1); - i++; + uriptr = REL_PTR(hdr, uri_str.s); + if(uri_str.len > 255 || uriptr > hdrlen) { + LM_ERR("uri too long, or out of the sip_msg bounds\n"); + return -1; + } + payload[0] = uriptr; + payload[1] = (unsigned char)uri_str.len; + if(uri_parsed->user.s && uri_parsed->user.len) { + flags1 |= USER_F; + payload[i++] = REL_PTR(uri_str.s, uri_parsed->user.s); + } + if(uri_parsed->passwd.s && uri_parsed->passwd.len) { + flags1 |= PASSWORD_F; + payload[i++] = REL_PTR(uri_str.s, uri_parsed->passwd.s); + } + if(uri_parsed->host.s && uri_parsed->host.len) { + flags1 |= HOST_F; + payload[i++] = REL_PTR(uri_str.s, uri_parsed->host.s); + } + if(uri_parsed->port.s && uri_parsed->port.len) { + flags1 |= PORT_F; + payload[i++] = REL_PTR(uri_str.s, uri_parsed->port.s); + } + if(uri_parsed->params.s && uri_parsed->params.len) { + flags1 |= PARAMETERS_F; + payload[i++] = REL_PTR(uri_str.s, uri_parsed->params.s); + } + if(uri_parsed->headers.s && uri_parsed->headers.len) { + flags1 |= HEADERS_F; + payload[i++] = REL_PTR(uri_str.s, uri_parsed->headers.s); + } + payload[i] = (unsigned char)(uri_str.len + 1); + i++; - if(uri_parsed->transport.s && uri_parsed->transport.len){ - flags2 |= TRANSPORT_F; - payload[i]=REL_PTR(uri_str.s,uri_parsed->transport.s); - payload[i+1]=(unsigned char)(uri_parsed->transport.len); - i+=2; - } - if(uri_parsed->ttl.s && uri_parsed->ttl.len){ - flags2 |= TTL_F; - payload[i]=REL_PTR(uri_str.s,uri_parsed->ttl.s); - payload[i+1]=(unsigned char)uri_parsed->ttl.len; - i+=2; - } - if(uri_parsed->user_param.s && uri_parsed->user_param.len){ - flags2 |= USER_F; - payload[i]=REL_PTR(uri_str.s,uri_parsed->user_param.s); - payload[i+1]=(unsigned char)uri_parsed->user_param.len; - i+=2; - } - if(uri_parsed->method.s && uri_parsed->method.len){ - flags2 |= METHOD_F; - payload[i]=REL_PTR(uri_str.s,uri_parsed->method.s); - payload[i+1]=(unsigned char)uri_parsed->method.len; - i+=2; - } - if(uri_parsed->maddr.s && uri_parsed->maddr.len){ - flags2 |= MADDR_F; - payload[i]=REL_PTR(uri_str.s,uri_parsed->maddr.s); - payload[i+1]=(unsigned char)uri_parsed->maddr.len; - i+=2; - } - if(uri_parsed->lr.s && uri_parsed->lr.len){ - flags2 |= LR_F; - payload[i]=REL_PTR(uri_str.s,uri_parsed->lr.s); - payload[i+1]=(unsigned char)uri_parsed->lr.len; - i+=2; - } - /*in parse_uri, when there's a user=phone, the type + if(uri_parsed->transport.s && uri_parsed->transport.len) { + flags2 |= TRANSPORT_F; + payload[i] = REL_PTR(uri_str.s, uri_parsed->transport.s); + payload[i + 1] = (unsigned char)(uri_parsed->transport.len); + i += 2; + } + if(uri_parsed->ttl.s && uri_parsed->ttl.len) { + flags2 |= TTL_F; + payload[i] = REL_PTR(uri_str.s, uri_parsed->ttl.s); + payload[i + 1] = (unsigned char)uri_parsed->ttl.len; + i += 2; + } + if(uri_parsed->user_param.s && uri_parsed->user_param.len) { + flags2 |= USER_F; + payload[i] = REL_PTR(uri_str.s, uri_parsed->user_param.s); + payload[i + 1] = (unsigned char)uri_parsed->user_param.len; + i += 2; + } + if(uri_parsed->method.s && uri_parsed->method.len) { + flags2 |= METHOD_F; + payload[i] = REL_PTR(uri_str.s, uri_parsed->method.s); + payload[i + 1] = (unsigned char)uri_parsed->method.len; + i += 2; + } + if(uri_parsed->maddr.s && uri_parsed->maddr.len) { + flags2 |= MADDR_F; + payload[i] = REL_PTR(uri_str.s, uri_parsed->maddr.s); + payload[i + 1] = (unsigned char)uri_parsed->maddr.len; + i += 2; + } + if(uri_parsed->lr.s && uri_parsed->lr.len) { + flags2 |= LR_F; + payload[i] = REL_PTR(uri_str.s, uri_parsed->lr.s); + payload[i + 1] = (unsigned char)uri_parsed->lr.len; + i += 2; + } + /*in parse_uri, when there's a user=phone, the type * is set to TEL_URI_T, even if there's a sip: in the beginning * so lets check it by ourselves: switch(uri_parsed->type){ @@ -207,244 +208,271 @@ int encode_uri2(char *hdr,int hdrlen,str uri_str, struct sip_uri *uri_parsed,uns default: return -1; }*/ -#define SIP_SCH 0x3a706973 -#define SIPS_SCH 0x73706973 -#define TEL_SCH 0x3a6c6574 -#define TELS_SCH 0x736c6574 - scheme=uri_str.s[0]+(uri_str.s[1]<<8)+(uri_str.s[2]<<16)+(uri_str.s[3]<<24); - scheme|=0x20202020; - if (scheme==SIP_SCH){ - flags1 |= SIP_OR_TEL_F; - }else if(scheme==SIPS_SCH){ - if(uri_str.s[4]==':'){ - flags1 |= (SIP_OR_TEL_F|SECURE_F); - }else goto error; - }else if (scheme==TEL_SCH){ - /*nothing*/ - }else if (scheme==TELS_SCH){ - if(uri_str.s[4]==':'){ - flags1 |= SECURE_F; - } - }else goto error; - - payload[2]=flags1; - payload[3]=flags2; - j=i; - i+=encode_parameters(&payload[i],uri_parsed->params.s,uri_str.s,&uri_parsed->params.len,'u'); - if(iparams.s, uri_str.s, + &uri_parsed->params.len, 'u'); + if(i < j) + goto error; + return i; error: - return -1; + return -1; } -int print_encoded_uri(FILE *fd,unsigned char *payload,int paylen,char *hdrstart,int hdrlen,char *prefix) +int print_encoded_uri(FILE *fd, unsigned char *payload, int paylen, + char *hdrstart, int hdrlen, char *prefix) { - int i=4,j=0;/*1*pointer+1*len+2*flags*/ - unsigned char uriidx=0,flags1=0,flags2=0,urilen; - char *ch_uriptr,*uritype=NULL,*secure=NULL; + int i = 4, j = 0; /*1*pointer+1*len+2*flags*/ + unsigned char uriidx = 0, flags1 = 0, flags2 = 0, urilen; + char *ch_uriptr, *uritype = NULL, *secure = NULL; - uriidx=payload[0]; - fprintf(fd,"%s",prefix); - for(j=0;jhdrlen){ - fprintf(fd,"bad index for start of uri: hdrlen=%d uri_index=%d\n",hdrlen,uriidx); - return -1; - } - ch_uriptr = hdrstart+uriidx; - urilen=payload[1]; - flags1=payload[2]; - flags2=payload[3]; - fprintf(fd,"%sURI:[%.*s]\n",prefix,urilen,ch_uriptr); - uritype=flags1&SIP_OR_TEL_F?"SIP":"TEL"; - secure=flags1&SECURE_F?"S":""; - fprintf(fd,"%s TYPE:[%s%s]\n",prefix,uritype,secure); - if(flags1 & USER_F){ - fprintf(fd,"%s USER:[%.*s]\n",prefix,(payload[i+1]-1)-payload[i],&ch_uriptr[payload[i]]); - ++i; - } - if(flags1 & PASSWORD_F){ - fprintf(fd,"%s PASSWORD=[%.*s]\n",prefix,(payload[i+1]-1)-payload[i],&ch_uriptr[payload[i]]); - ++i; - } - if(flags1 & HOST_F){ - fprintf(fd,"%s HOST=[%.*s]\n",prefix,(payload[i+1]-1)-payload[i],&ch_uriptr[payload[i]]); - ++i; - } - if(flags1 & PORT_F){ - fprintf(fd,"%s PORT=[%.*s]\n",prefix,(payload[i+1]-1)-payload[i],&ch_uriptr[payload[i]]); - ++i; - } - if(flags1 & PARAMETERS_F){ - fprintf(fd,"%s PARAMETERS=[%.*s]\n",prefix,(payload[i+1]-1)-payload[i],&ch_uriptr[payload[i]]); - ++i; - } - if(flags1 & HEADERS_F){ - fprintf(fd,"%s HEADERS=[%.*s]\n",prefix,(payload[i+1]-1)-payload[i],&ch_uriptr[payload[i]]); - ++i; - } - ++i; - if(flags2 & TRANSPORT_F){ - fprintf(fd,"%s TRANSPORT=[%.*s]\n",prefix,payload[i+1],&ch_uriptr[payload[i]]); - i+=2; - } - if(flags2 & TTL_F){ - fprintf(fd,"%s TTL_F=[%.*s]\n",prefix,payload[i+1],&ch_uriptr[payload[i]]); - i+=2; - } - if(flags2 & USER_F){ - fprintf(fd,"%s USER_F=[%.*s]\n",prefix,payload[i+1],&ch_uriptr[payload[i]]); - i+=2; - } - if(flags2 & METHOD_F){ - fprintf(fd,"%s METHOD_F=[%.*s]\n",prefix,payload[i+1],&ch_uriptr[payload[i]]); - i+=2; - } - if(flags2 & MADDR_F){ - fprintf(fd,"%s MADDR_F=[%.*s]\n",prefix,payload[i+1],&ch_uriptr[payload[i]]); - i+=2; - } - if(flags2 & LR_F){ - fprintf(fd,"%s LR_F=[%.*s]\n",prefix,payload[i+1],&ch_uriptr[payload[i]]); - i+=2; - } - print_encoded_parameters(fd,&payload[i],ch_uriptr,paylen-i,prefix); - return 0; + uriidx = payload[0]; + fprintf(fd, "%s", prefix); + for(j = 0; j < paylen; j++) + fprintf(fd, "%s%d%s", j == 0 ? "ENCODED-URI:[" : ":", payload[j], + j == paylen - 1 ? "]\n" : ""); + if(uriidx > hdrlen) { + fprintf(fd, "bad index for start of uri: hdrlen=%d uri_index=%d\n", + hdrlen, uriidx); + return -1; + } + ch_uriptr = hdrstart + uriidx; + urilen = payload[1]; + flags1 = payload[2]; + flags2 = payload[3]; + fprintf(fd, "%sURI:[%.*s]\n", prefix, urilen, ch_uriptr); + uritype = flags1 & SIP_OR_TEL_F ? "SIP" : "TEL"; + secure = flags1 & SECURE_F ? "S" : ""; + fprintf(fd, "%s TYPE:[%s%s]\n", prefix, uritype, secure); + if(flags1 & USER_F) { + fprintf(fd, "%s USER:[%.*s]\n", prefix, + (payload[i + 1] - 1) - payload[i], &ch_uriptr[payload[i]]); + ++i; + } + if(flags1 & PASSWORD_F) { + fprintf(fd, "%s PASSWORD=[%.*s]\n", prefix, + (payload[i + 1] - 1) - payload[i], &ch_uriptr[payload[i]]); + ++i; + } + if(flags1 & HOST_F) { + fprintf(fd, "%s HOST=[%.*s]\n", prefix, + (payload[i + 1] - 1) - payload[i], &ch_uriptr[payload[i]]); + ++i; + } + if(flags1 & PORT_F) { + fprintf(fd, "%s PORT=[%.*s]\n", prefix, + (payload[i + 1] - 1) - payload[i], &ch_uriptr[payload[i]]); + ++i; + } + if(flags1 & PARAMETERS_F) { + fprintf(fd, "%s PARAMETERS=[%.*s]\n", prefix, + (payload[i + 1] - 1) - payload[i], &ch_uriptr[payload[i]]); + ++i; + } + if(flags1 & HEADERS_F) { + fprintf(fd, "%s HEADERS=[%.*s]\n", prefix, + (payload[i + 1] - 1) - payload[i], &ch_uriptr[payload[i]]); + ++i; + } + ++i; + if(flags2 & TRANSPORT_F) { + fprintf(fd, "%s TRANSPORT=[%.*s]\n", prefix, payload[i + 1], + &ch_uriptr[payload[i]]); + i += 2; + } + if(flags2 & TTL_F) { + fprintf(fd, "%s TTL_F=[%.*s]\n", prefix, payload[i + 1], + &ch_uriptr[payload[i]]); + i += 2; + } + if(flags2 & USER_F) { + fprintf(fd, "%s USER_F=[%.*s]\n", prefix, payload[i + 1], + &ch_uriptr[payload[i]]); + i += 2; + } + if(flags2 & METHOD_F) { + fprintf(fd, "%s METHOD_F=[%.*s]\n", prefix, payload[i + 1], + &ch_uriptr[payload[i]]); + i += 2; + } + if(flags2 & MADDR_F) { + fprintf(fd, "%s MADDR_F=[%.*s]\n", prefix, payload[i + 1], + &ch_uriptr[payload[i]]); + i += 2; + } + if(flags2 & LR_F) { + fprintf(fd, "%s LR_F=[%.*s]\n", prefix, payload[i + 1], + &ch_uriptr[payload[i]]); + i += 2; + } + print_encoded_parameters(fd, &payload[i], ch_uriptr, paylen - i, prefix); + return 0; } -int print_uri_junit_tests(char *hdrstart,int hdrlen,unsigned char *payload,int paylen,FILE *fd,char also_hdr,char *prefix) +int print_uri_junit_tests(char *hdrstart, int hdrlen, unsigned char *payload, + int paylen, FILE *fd, char also_hdr, char *prefix) { - int i=4,k=0,m=0;/*1*pointer+1*len+2*flags*/ - unsigned char uriidx=0,flags1=0,flags2=0,urilen; - char *ch_uriptr,*aux,*aux2,*aux3,*uritype=NULL,*secure=NULL; + int i = 4, k = 0, m = 0; /*1*pointer+1*len+2*flags*/ + unsigned char uriidx = 0, flags1 = 0, flags2 = 0, urilen; + char *ch_uriptr, *aux, *aux2, *aux3, *uritype = NULL, *secure = NULL; - uriidx=payload[0]; - if(uriidx>hdrlen){ - fprintf(fd,"bad index for start of uri: hdrlen=%d uri_index=%d\n",hdrlen,uriidx); - return -1; - } + uriidx = payload[0]; + if(uriidx > hdrlen) { + fprintf(fd, "bad index for start of uri: hdrlen=%d uri_index=%d\n", + hdrlen, uriidx); + return -1; + } - if(also_hdr) - dump_standard_hdr_test(hdrstart,hdrlen,payload,paylen,fd); - ch_uriptr = hdrstart+uriidx; - urilen=payload[1]; - flags1=payload[2]; - flags2=payload[3]; - fprintf(fd,"%stoString=(S)%.*s\n",prefix,urilen,ch_uriptr); - uritype=flags1&SIP_OR_TEL_F?"sip":"tel"; - secure=flags1&SECURE_F?"s":""; - fprintf(fd,"%sgetScheme=(S)%s%s\n",prefix,uritype,secure); - fprintf(fd,"%sisSecure=(B)%s\n",prefix,flags1&SECURE_F?"true":"false"); - fprintf(fd,"%sisSipURI=(B)%s\n",prefix,"true"); - fprintf(fd,"%sgetUser=(S)",prefix); - if(flags1 & USER_F){ - fprintf(fd,"%.*s\n",(payload[i+1]-1)-payload[i],&ch_uriptr[payload[i]]); - ++i; - }else - fprintf(fd,"(null)\n"); - fprintf(fd,"%sgetUserPassword=(S)",prefix); - if(flags1 & PASSWORD_F){ - fprintf(fd,"%.*s\n",(payload[i+1]-1)-payload[i],&ch_uriptr[payload[i]]); - ++i; - }else - fprintf(fd,"(null)\n"); - fprintf(fd,"%sgetHost=(S)",prefix); - if(flags1 & HOST_F){ - fprintf(fd,"%.*s\n",(payload[i+1]-1)-payload[i],&ch_uriptr[payload[i]]); - ++i; - }else - fprintf(fd,"(null)\n");/*can't happen*/ - fprintf(fd,"%sgetPort=(I)",prefix); - if(flags1 & PORT_F){ - fprintf(fd,"%.*s\n",(payload[i+1]-1)-payload[i],&ch_uriptr[payload[i]]); - ++i; - }else - fprintf(fd,"(null)\n"); - /*user=phone;transport=udp*/ - if(flags1 & PARAMETERS_F){ - aux=&ch_uriptr[payload[i]]; - aux2=NULL; - aux3=aux; - m=(payload[i+1]-1-payload[i]); - fprintf(fd,"%sgetParameter=(SAVP)",prefix);/*SVP = Attribute Value Pair*/ - for(k=0;k<=m;k++){ - if((aux3[k]==';'||(k==m)) && aux2==NULL){/*no parameterValue was found*/ - fprintf(fd,"%.*s=;",(int)(aux3-aux+k),aux); - aux2=NULL;/*resets the parameterValue-start pointer*/ - aux=aux3+1+k;/*points to the next parameter*/ - }else - if((aux3[k]==';'||(k==m)) && aux2!=NULL){ - fprintf(fd,"%.*s=%.*s;",(int)(aux2-aux),aux,(int)(aux3-aux2-1+k),aux2+1); - aux2=NULL; - aux=aux3+1+k; - } else - if(aux3[k]=='='){ - aux2=aux3+k; - } - } - fprintf(fd,"\n"); - ++i; - } - if(flags1 & HEADERS_F){ - aux=&ch_uriptr[payload[i]]; - aux2=NULL; - aux3=aux; - m=(payload[i+1]-1-payload[i]); - fprintf(fd,"%sgetHeader=(SAVP)",prefix); - for(k=0;k<=m;k++){ - if((aux3[k]==';'||(k==m)) && aux2==NULL){/*no parameterValue was found*/ - fprintf(fd,"%.*s=;",(int)(aux3-aux+k),aux); - aux2=NULL;/*resets the parameterValue-start pointer*/ - aux=aux3+1+k;/*points to the next parameter*/ - }else - if((aux3[k]==';'||(k==m)) && aux2!=NULL){ - fprintf(fd,"%.*s=%.*s;",(int)(aux2-aux),aux,(int)(aux3-aux2-1+k),aux2+1); - aux2=NULL; - aux=aux3+1+k; - } else - if(aux3[k]=='='){ - aux2=aux3+k; - } - } - fprintf(fd,"\n"); - ++i; - } - ++i; - fprintf(fd,"%sgetTransportParam=(S)",prefix); - if(flags2 & TRANSPORT_F){ - fprintf(fd,"%.*s\n",payload[i+1],&ch_uriptr[payload[i]]); - i+=2; - }else - fprintf(fd,"(null)\n"); - fprintf(fd,"%sgetTTLparam=(I)",prefix); - if(flags2 & TTL_F){ - fprintf(fd,"%.*s\n",payload[i+1],&ch_uriptr[payload[i]]); - i+=2; - }else - fprintf(fd,"(null)\n"); - fprintf(fd,"%sgetUserParam=(S)",prefix); - if(flags2 & USER_F){ - fprintf(fd,"%.*s\n",payload[i+1],&ch_uriptr[payload[i]]); - i+=2; - }else - fprintf(fd,"(null)\n"); - fprintf(fd,"%sgetMethodParam=(S)",prefix); - if(flags2 & METHOD_F){ - fprintf(fd,"%.*s\n",payload[i+1],&ch_uriptr[payload[i]]); - i+=2; - }else - fprintf(fd,"(null)\n"); - fprintf(fd,"%sgetMAddrParam=(S)",prefix); - if(flags2 & MADDR_F){ - fprintf(fd,"%.*s\n",payload[i+1],&ch_uriptr[payload[i]]); - i+=2; - }else - fprintf(fd,"(null)\n"); - if(flags2 & LR_F){ - i+=2; - } - fprintf(fd,"\n"); - return 0; + if(also_hdr) + dump_standard_hdr_test(hdrstart, hdrlen, payload, paylen, fd); + ch_uriptr = hdrstart + uriidx; + urilen = payload[1]; + flags1 = payload[2]; + flags2 = payload[3]; + fprintf(fd, "%stoString=(S)%.*s\n", prefix, urilen, ch_uriptr); + uritype = flags1 & SIP_OR_TEL_F ? "sip" : "tel"; + secure = flags1 & SECURE_F ? "s" : ""; + fprintf(fd, "%sgetScheme=(S)%s%s\n", prefix, uritype, secure); + fprintf(fd, "%sisSecure=(B)%s\n", prefix, + flags1 & SECURE_F ? "true" : "false"); + fprintf(fd, "%sisSipURI=(B)%s\n", prefix, "true"); + fprintf(fd, "%sgetUser=(S)", prefix); + if(flags1 & USER_F) { + fprintf(fd, "%.*s\n", (payload[i + 1] - 1) - payload[i], + &ch_uriptr[payload[i]]); + ++i; + } else + fprintf(fd, "(null)\n"); + fprintf(fd, "%sgetUserPassword=(S)", prefix); + if(flags1 & PASSWORD_F) { + fprintf(fd, "%.*s\n", (payload[i + 1] - 1) - payload[i], + &ch_uriptr[payload[i]]); + ++i; + } else + fprintf(fd, "(null)\n"); + fprintf(fd, "%sgetHost=(S)", prefix); + if(flags1 & HOST_F) { + fprintf(fd, "%.*s\n", (payload[i + 1] - 1) - payload[i], + &ch_uriptr[payload[i]]); + ++i; + } else + fprintf(fd, "(null)\n"); /*can't happen*/ + fprintf(fd, "%sgetPort=(I)", prefix); + if(flags1 & PORT_F) { + fprintf(fd, "%.*s\n", (payload[i + 1] - 1) - payload[i], + &ch_uriptr[payload[i]]); + ++i; + } else + fprintf(fd, "(null)\n"); + /*user=phone;transport=udp*/ + if(flags1 & PARAMETERS_F) { + aux = &ch_uriptr[payload[i]]; + aux2 = NULL; + aux3 = aux; + m = (payload[i + 1] - 1 - payload[i]); + fprintf(fd, "%sgetParameter=(SAVP)", + prefix); /*SVP = Attribute Value Pair*/ + for(k = 0; k <= m; k++) { + if((aux3[k] == ';' || (k == m)) + && aux2 == NULL) { /*no parameterValue was found*/ + fprintf(fd, "%.*s=;", (int)(aux3 - aux + k), aux); + aux2 = NULL; /*resets the parameterValue-start pointer*/ + aux = aux3 + 1 + k; /*points to the next parameter*/ + } else if((aux3[k] == ';' || (k == m)) && aux2 != NULL) { + fprintf(fd, "%.*s=%.*s;", (int)(aux2 - aux), aux, + (int)(aux3 - aux2 - 1 + k), aux2 + 1); + aux2 = NULL; + aux = aux3 + 1 + k; + } else if(aux3[k] == '=') { + aux2 = aux3 + k; + } + } + fprintf(fd, "\n"); + ++i; + } + if(flags1 & HEADERS_F) { + aux = &ch_uriptr[payload[i]]; + aux2 = NULL; + aux3 = aux; + m = (payload[i + 1] - 1 - payload[i]); + fprintf(fd, "%sgetHeader=(SAVP)", prefix); + for(k = 0; k <= m; k++) { + if((aux3[k] == ';' || (k == m)) + && aux2 == NULL) { /*no parameterValue was found*/ + fprintf(fd, "%.*s=;", (int)(aux3 - aux + k), aux); + aux2 = NULL; /*resets the parameterValue-start pointer*/ + aux = aux3 + 1 + k; /*points to the next parameter*/ + } else if((aux3[k] == ';' || (k == m)) && aux2 != NULL) { + fprintf(fd, "%.*s=%.*s;", (int)(aux2 - aux), aux, + (int)(aux3 - aux2 - 1 + k), aux2 + 1); + aux2 = NULL; + aux = aux3 + 1 + k; + } else if(aux3[k] == '=') { + aux2 = aux3 + k; + } + } + fprintf(fd, "\n"); + ++i; + } + ++i; + fprintf(fd, "%sgetTransportParam=(S)", prefix); + if(flags2 & TRANSPORT_F) { + fprintf(fd, "%.*s\n", payload[i + 1], &ch_uriptr[payload[i]]); + i += 2; + } else + fprintf(fd, "(null)\n"); + fprintf(fd, "%sgetTTLparam=(I)", prefix); + if(flags2 & TTL_F) { + fprintf(fd, "%.*s\n", payload[i + 1], &ch_uriptr[payload[i]]); + i += 2; + } else + fprintf(fd, "(null)\n"); + fprintf(fd, "%sgetUserParam=(S)", prefix); + if(flags2 & USER_F) { + fprintf(fd, "%.*s\n", payload[i + 1], &ch_uriptr[payload[i]]); + i += 2; + } else + fprintf(fd, "(null)\n"); + fprintf(fd, "%sgetMethodParam=(S)", prefix); + if(flags2 & METHOD_F) { + fprintf(fd, "%.*s\n", payload[i + 1], &ch_uriptr[payload[i]]); + i += 2; + } else + fprintf(fd, "(null)\n"); + fprintf(fd, "%sgetMAddrParam=(S)", prefix); + if(flags2 & MADDR_F) { + fprintf(fd, "%.*s\n", payload[i + 1], &ch_uriptr[payload[i]]); + i += 2; + } else + fprintf(fd, "(null)\n"); + if(flags2 & LR_F) { + i += 2; + } + fprintf(fd, "\n"); + return 0; } diff --git a/src/modules/seas/encode_uri.h b/src/modules/seas/encode_uri.h index d15f56435e8..0a6074343ee 100644 --- a/src/modules/seas/encode_uri.h +++ b/src/modules/seas/encode_uri.h @@ -22,24 +22,27 @@ #include "../../core/str.h" #include "../../core/parser/msg_parser.h" -#define SIP_OR_TEL_F 0x01 -#define SECURE_F 0x02 -#define USER_F 0x04 -#define PASSWORD_F 0x08 -#define HOST_F 0x10 -#define PORT_F 0x20 -#define PARAMETERS_F 0x40 -#define HEADERS_F 0x80 +#define SIP_OR_TEL_F 0x01 +#define SECURE_F 0x02 +#define USER_F 0x04 +#define PASSWORD_F 0x08 +#define HOST_F 0x10 +#define PORT_F 0x20 +#define PARAMETERS_F 0x40 +#define HEADERS_F 0x80 -#define TRANSPORT_F 0x01 -#define TTL_F 0x02 -#define USER_F 0x04 -#define METHOD_F 0x08 -#define MADDR_F 0x10 -#define LR_F 0x20 +#define TRANSPORT_F 0x01 +#define TTL_F 0x02 +#define USER_F 0x04 +#define METHOD_F 0x08 +#define MADDR_F 0x10 +#define LR_F 0x20 -#define MAX_XURI_LEN 23 +#define MAX_XURI_LEN 23 -int encode_uri2(char *hdr,int hdrlen,str uri_str, struct sip_uri *uri_parsed,unsigned char *where); -int print_encoded_uri(FILE* fd,unsigned char *payload,int paylen,char *hdr,int hdrlen,char *prefix); -int print_uri_junit_tests(char *hdrstart,int hdrlen,unsigned char *payload,int paylen,FILE* fd,char also_hdr,char *prefix); +int encode_uri2(char *hdr, int hdrlen, str uri_str, struct sip_uri *uri_parsed, + unsigned char *where); +int print_encoded_uri(FILE *fd, unsigned char *payload, int paylen, char *hdr, + int hdrlen, char *prefix); +int print_uri_junit_tests(char *hdrstart, int hdrlen, unsigned char *payload, + int paylen, FILE *fd, char also_hdr, char *prefix); diff --git a/src/modules/seas/encode_via.c b/src/modules/seas/encode_via.c index 2957161a0d2..285b6b69a2a 100644 --- a/src/modules/seas/encode_via.c +++ b/src/modules/seas/encode_via.c @@ -48,15 +48,15 @@ #include "encode_header.h" #include "encode_parameters.h" -#define HAS_PARAMS_F 0x01 -#define HAS_BRANCH_F 0x02 -#define HAS_RECEIVED_F 0x04 -#define HAS_RPORT_F 0x08 -#define HAS_I_F 0x10 -#define HAS_ALIAS_F 0x20 -#define HAS_PORT_F 0x40 +#define HAS_PARAMS_F 0x01 +#define HAS_BRANCH_F 0x02 +#define HAS_RECEIVED_F 0x04 +#define HAS_RPORT_F 0x08 +#define HAS_I_F 0x10 +#define HAS_ALIAS_F 0x20 +#define HAS_PORT_F 0x40 -#define REL_PTR(a,b) (unsigned char)((b)-(a)) +#define REL_PTR(a, b) (unsigned char)((b) - (a)) /* * encodes a (maybe aggregated) via header. @@ -66,26 +66,28 @@ * N: fore each via present, the length of the via * N*M: the via structures concatenated */ -int encode_via_body(char *hdr,int hdrlen,struct via_body *via_parsed,unsigned char *where) +int encode_via_body(char *hdr, int hdrlen, struct via_body *via_parsed, + unsigned char *where) { - int i=0,k,via_offset; - unsigned char tmp[500]; - struct via_body *myvia; - - if(via_parsed) - for(via_offset=0,i=0,myvia=via_parsed;myvia;myvia=myvia->next,i++){ - if((k=encode_via(hdr,hdrlen,myvia,&tmp[via_offset]))<0){ - LM_ERR("failed to parse via number %d\n",i); - return -1; - } - where[2+i]=(unsigned char)k; - via_offset+=k; - } - else - return -1; - where[1]=(unsigned char)i;/*how may vias there are*/ - memcpy(&where[2+i],tmp,via_offset); - return 2+i+via_offset; + int i = 0, k, via_offset; + unsigned char tmp[500]; + struct via_body *myvia; + + if(via_parsed) + for(via_offset = 0, i = 0, myvia = via_parsed; myvia; + myvia = myvia->next, i++) { + if((k = encode_via(hdr, hdrlen, myvia, &tmp[via_offset])) < 0) { + LM_ERR("failed to parse via number %d\n", i); + return -1; + } + where[2 + i] = (unsigned char)k; + via_offset += k; + } + else + return -1; + where[1] = (unsigned char)i; /*how may vias there are*/ + memcpy(&where[2 + i], tmp, via_offset); + return 2 + i + via_offset; } /* Encoder for vias. @@ -94,152 +96,176 @@ int encode_via_body(char *hdr,int hdrlen,struct via_body *via_parsed,unsigned ch * 1: flags * */ -int encode_via(char *hdrstart,int hdrlen,struct via_body *body,unsigned char *where) +int encode_via( + char *hdrstart, int hdrlen, struct via_body *body, unsigned char *where) { - int i;/* 1*flags + 1*hostport_len*/ - unsigned char flags=0; - - where[1]=REL_PTR(hdrstart,body->name.s); - where[2]=REL_PTR(hdrstart,body->version.s); - where[3]=REL_PTR(hdrstart,body->transport.s); - where[4]=REL_PTR(hdrstart,body->transport.s+body->transport.len+1); - where[5]=REL_PTR(hdrstart,body->host.s); - if(body->port_str.s && body->port_str.len){ - flags|=HAS_PORT_F; - where[6]=REL_PTR(hdrstart,body->port_str.s); - where[7]=REL_PTR(hdrstart,body->port_str.s+body->port_str.len+1); - i=8; - }else{ - where[6]=REL_PTR(hdrstart,body->host.s+body->host.len+1); - i=7; - } - if(body->params.s && body->params.len){ - flags|=HAS_PARAMS_F; - where[i++]=REL_PTR(hdrstart,body->params.s); - where[i++]=(unsigned char)body->params.len; - } - if(body->branch && body->branch->value.s && body->branch->value.len){ - flags|=HAS_BRANCH_F; - where[i++]=REL_PTR(hdrstart,body->branch->value.s); - where[i++]=(unsigned char)body->branch->value.len; - } - if(body->received && body->received->value.s && body->received->value.len){ - flags|=HAS_RECEIVED_F; - where[i++]=REL_PTR(hdrstart,body->received->value.s); - where[i++]=(unsigned char)body->received->value.len; - } - if(body->rport && body->rport->value.s && body->rport->value.len){ - flags|=HAS_RPORT_F; - where[i++]=REL_PTR(hdrstart,body->rport->value.s); - where[i++]=(unsigned char)body->rport->value.len; - } - if(body->i && body->i->value.s && body->i->value.len){ - flags|=HAS_I_F; - where[i++]=REL_PTR(hdrstart,body->i->value.s); - where[i++]=(unsigned char)body->i->value.len; - } - if(body->alias && body->alias->value.s && body->alias->value.len){ - flags|=HAS_ALIAS_F; - where[i++]=REL_PTR(hdrstart,body->alias->value.s); - where[i++]=(unsigned char)body->alias->value.len; - } - - where[0]=flags; - i+=encode_parameters(&where[i],body->param_lst,hdrstart,(void *)body,'v'); - return i; + int i; /* 1*flags + 1*hostport_len*/ + unsigned char flags = 0; + + where[1] = REL_PTR(hdrstart, body->name.s); + where[2] = REL_PTR(hdrstart, body->version.s); + where[3] = REL_PTR(hdrstart, body->transport.s); + where[4] = REL_PTR(hdrstart, body->transport.s + body->transport.len + 1); + where[5] = REL_PTR(hdrstart, body->host.s); + if(body->port_str.s && body->port_str.len) { + flags |= HAS_PORT_F; + where[6] = REL_PTR(hdrstart, body->port_str.s); + where[7] = REL_PTR(hdrstart, body->port_str.s + body->port_str.len + 1); + i = 8; + } else { + where[6] = REL_PTR(hdrstart, body->host.s + body->host.len + 1); + i = 7; + } + if(body->params.s && body->params.len) { + flags |= HAS_PARAMS_F; + where[i++] = REL_PTR(hdrstart, body->params.s); + where[i++] = (unsigned char)body->params.len; + } + if(body->branch && body->branch->value.s && body->branch->value.len) { + flags |= HAS_BRANCH_F; + where[i++] = REL_PTR(hdrstart, body->branch->value.s); + where[i++] = (unsigned char)body->branch->value.len; + } + if(body->received && body->received->value.s && body->received->value.len) { + flags |= HAS_RECEIVED_F; + where[i++] = REL_PTR(hdrstart, body->received->value.s); + where[i++] = (unsigned char)body->received->value.len; + } + if(body->rport && body->rport->value.s && body->rport->value.len) { + flags |= HAS_RPORT_F; + where[i++] = REL_PTR(hdrstart, body->rport->value.s); + where[i++] = (unsigned char)body->rport->value.len; + } + if(body->i && body->i->value.s && body->i->value.len) { + flags |= HAS_I_F; + where[i++] = REL_PTR(hdrstart, body->i->value.s); + where[i++] = (unsigned char)body->i->value.len; + } + if(body->alias && body->alias->value.s && body->alias->value.len) { + flags |= HAS_ALIAS_F; + where[i++] = REL_PTR(hdrstart, body->alias->value.s); + where[i++] = (unsigned char)body->alias->value.len; + } + + where[0] = flags; + i += encode_parameters( + &where[i], body->param_lst, hdrstart, (void *)body, 'v'); + return i; } -int print_encoded_via_body(FILE *fd,char *hdr,int hdrlen,unsigned char *payload,int paylen,char *prefix) +int print_encoded_via_body(FILE *fd, char *hdr, int hdrlen, + unsigned char *payload, int paylen, char *prefix) { - unsigned char numvias; - int i,offset; - - fprintf(fd,"%s",prefix); - for(i=0;i/*setsockopt,bind,accept,fork,pid_t,waitpid*/ -#include /*setsockopt,bind,accept,listen*/ +#include /*setsockopt,bind,accept,fork,pid_t,waitpid*/ +#include /*setsockopt,bind,accept,listen*/ #include /*TCP_NODELAY*/ -#include /*strcmp,memset,memcmp*/ -#include /*errno*/ -#include /*close(),read(),pipe,fork,pid_t*/ -#include /*poll*/ -#include /*signal*/ -#include /*time*/ -#include /*waitpid*/ +#include /*strcmp,memset,memcmp*/ +#include /*errno*/ +#include /*close(),read(),pipe,fork,pid_t*/ +#include /*poll*/ +#include /*signal*/ +#include /*time*/ +#include /*waitpid*/ -#include "../../core/ip_addr.h" /*sockaddr_union, ip_addr*/ -#include "../../core/hashes.h" /*T_TABLE_POWER*/ -#include "../../core/mem/mem.h" /*pkg_malloc*/ +#include "../../core/ip_addr.h" /*sockaddr_union, ip_addr*/ +#include "../../core/hashes.h" /*T_TABLE_POWER*/ +#include "../../core/mem/mem.h" /*pkg_malloc*/ #include "../../core/mem/shm_mem.h" /*shm_malloc*/ -#include "../../core/dprint.h" /*LM_**/ +#include "../../core/dprint.h" /*LM_**/ #include "../../core/locking.h" #include "../../core/cfg/cfg_struct.h" @@ -48,18 +48,12 @@ #define PING_OVER_FACTOR 2 #define MAX_WRITE_TRIES 10 -char *action_names[]={"NONE", - "PROVISIONAL_REPLY", - "FINAL_REPLY", - "REPLY_FIN_DLG", - "UAC_REQ", - "AC_RES_FAIL", - "STATELESS_MSG", - "AC_CANCEL", - "JAIN_PONG"}; +char *action_names[] = {"NONE", "PROVISIONAL_REPLY", "FINAL_REPLY", + "REPLY_FIN_DLG", "UAC_REQ", "AC_RES_FAIL", "STATELESS_MSG", "AC_CANCEL", + "JAIN_PONG"}; -struct unc_as unc_as_t[2*MAX_UNC_AS_NR]; +struct unc_as unc_as_t[2 * MAX_UNC_AS_NR]; /*this is for the Action Dispatcher Process */ struct as_entry *my_as; @@ -68,15 +62,17 @@ extern int sig_flag; static int process_event_reply(as_p as); static int handle_as_data(int fd); -static inline int print_sock_info(char *buffer,int wheremax,int *idx,struct socket_info *s,enum sip_protos type); +static inline int print_sock_info(char *buffer, int wheremax, int *idx, + struct socket_info *s, enum sip_protos type); static inline int send_sockinfo(int fd); -static inline int add_new_as(int event_idx,int action_idx,struct as_entry *as); +static inline int add_new_as( + int event_idx, int action_idx, struct as_entry *as); static int dispatch_relay(); -static int new_as_connect(int fd,char which); -static inline int read_name(int sock,char *dst,int dstlen); +static int new_as_connect(int fd, char which); +static inline int read_name(int sock, char *dst, int dstlen); static int handle_unc_as_data(int fd); -static int open_server_sockets(struct ip_addr *address,unsigned short port,int *fd); - +static int open_server_sockets( + struct ip_addr *address, unsigned short port, int *fd); /** Main loop for the Event Dispatcher process. @@ -84,256 +80,270 @@ static int open_server_sockets(struct ip_addr *address,unsigned short port,int * */ int dispatcher_main_loop(void) { - struct pollfd poll_fds[3+MAX_AS_NR],*poll_tmp; - int clean_index,i,j,k,fd,poll_events=0,socks[2],chld_status; - int as_nr,unc_as_nr; - pid_t chld; - struct timeval last_ping,now; - struct as_entry *as; + struct pollfd poll_fds[3 + MAX_AS_NR], *poll_tmp; + int clean_index, i, j, k, fd, poll_events = 0, socks[2], chld_status; + int as_nr, unc_as_nr; + pid_t chld; + struct timeval last_ping, now; + struct as_entry *as; - sig_flag=0; - is_dispatcher=1; - as_nr=0; + sig_flag = 0; + is_dispatcher = 1; + as_nr = 0; - timerclear(&last_ping); - timerclear(&now); - signal(SIGCHLD,seas_sighandler); - signal(SIGTERM,seas_sighandler); - signal(SIGUSR1,seas_sighandler); - signal(SIGINT, seas_sighandler); - signal(SIGKILL,seas_sighandler); + timerclear(&last_ping); + timerclear(&now); + signal(SIGCHLD, seas_sighandler); + signal(SIGTERM, seas_sighandler); + signal(SIGUSR1, seas_sighandler); + signal(SIGINT, seas_sighandler); + signal(SIGKILL, seas_sighandler); - strcpy(whoami,"Seas Event Dispatcher process"); - /*I set process_no to -1 because otherwise, the logging process confuses this process with another from SER + strcpy(whoami, "Seas Event Dispatcher process"); + /*I set process_no to -1 because otherwise, the logging process confuses this process with another from SER * (see LM_*() and dprint() and my_pid())*/ - process_no = -1; + process_no = -1; - if(open_server_sockets(seas_listen_ip,seas_listen_port,socks)==-1){ - LM_ERR("unable to open server sockets on dispatcher\n"); - return -1; - } - for(i=0;i<2;i++){ - poll_fds[i].fd=socks[i]; - poll_fds[i].revents=0; - poll_fds[i].events=POLLIN; - } - poll_fds[2].fd=read_pipe; - poll_fds[2].revents=0; - poll_fds[2].events=POLLIN;/*pollhup ?*/ + if(open_server_sockets(seas_listen_ip, seas_listen_port, socks) == -1) { + LM_ERR("unable to open server sockets on dispatcher\n"); + return -1; + } + for(i = 0; i < 2; i++) { + poll_fds[i].fd = socks[i]; + poll_fds[i].revents = 0; + poll_fds[i].events = POLLIN; + } + poll_fds[2].fd = read_pipe; + poll_fds[2].revents = 0; + poll_fds[2].events = POLLIN; /*pollhup ?*/ - poll_events=0; - unc_as_nr=0; + poll_events = 0; + unc_as_nr = 0; - if(use_ha) - spawn_pinger(); + if(use_ha) + spawn_pinger(); - while(1){ + while(1) { /* update the local config framework structures */ cfg_update(); - if(sig_flag==SIGCHLD){ - while ((chld=waitpid( -1, &chld_status, WNOHANG ))>0) { - if (WIFEXITED(chld_status)){ - LM_INFO("child process %d exited normally, status=%d\n", - chld,WEXITSTATUS(chld_status)); - }else if (WIFSIGNALED(chld_status)) { - LM_INFO("child process %d exited by a signal %d\n", - chld,WTERMSIG(chld_status)); - }else if (WIFSTOPPED(chld_status)) - LM_INFO("child process %d stopped by a signal %d\n", - chld,WSTOPSIG(chld_status)); - for (as=as_list;as;as=as->next) { - if(as->type!=AS_TYPE) - continue; - if(as->u.as.action_pid==chld){ - for(i=0;iu.as.event_fd));i++) - ; - if(i==as_nr){ - LM_ERR("Either the pinger has died or BUG found..\n"); - continue; - } - /*overwrite the obsolete 'i' position with the next position*/ - for(j=3+i;j<(as_nr+unc_as_nr+3-1);i++){ - poll_fds[j].fd=poll_fds[j+1].fd; - poll_fds[j].events=poll_fds[j+1].events; - poll_fds[j].revents=poll_fds[j+1].revents; - } - close(as->u.as.event_fd);/*close the socket fd*/ - if (as->u.as.ev_buffer.s) { - pkg_free(as->u.as.ev_buffer.s); - as->u.as.ev_buffer.s=(char *)0; - as->u.as.ev_buffer.len=0; - } - as->u.as.event_fd=as->u.as.action_fd=-1; - as->connected=0; - destroy_pingtable(&as->u.as.jain_pings); - destroy_pingtable(&as->u.as.servlet_pings); - as_nr--; - LM_WARN("client [%.*s] leaving (Action Dispatcher Process died !)\n", - as->name.len,as->name.s); - break; - }/*if(action_pid==chld)*/ - }/*for(as=as_list;as;as=as->next)*/ - }/*while(waitpid(-1)>0)*/ - }else if (sig_flag) { - LM_WARN("received signal != sigchld(%d)\n",sig_flag); - } - sig_flag=0; - clean_index=0; - LM_INFO("polling [2 ServSock] [1 pipe] [%d App Servers]" - " [%d Incomplete AS]\n",as_nr,unc_as_nr); - poll_events = poll(poll_fds,3+unc_as_nr+as_nr,-1); - if (poll_events == -1) { - if(errno==EINTR){ - /*handle the case a child has died. + if(sig_flag == SIGCHLD) { + while((chld = waitpid(-1, &chld_status, WNOHANG)) > 0) { + if(WIFEXITED(chld_status)) { + LM_INFO("child process %d exited normally, status=%d\n", + chld, WEXITSTATUS(chld_status)); + } else if(WIFSIGNALED(chld_status)) { + LM_INFO("child process %d exited by a signal %d\n", chld, + WTERMSIG(chld_status)); + } else if(WIFSTOPPED(chld_status)) + LM_INFO("child process %d stopped by a signal %d\n", chld, + WSTOPSIG(chld_status)); + for(as = as_list; as; as = as->next) { + if(as->type != AS_TYPE) + continue; + if(as->u.as.action_pid == chld) { + for(i = 0; i < as_nr + && ((poll_fds[3 + i].fd) + != (as->u.as.event_fd)); + i++) + ; + if(i == as_nr) { + LM_ERR("Either the pinger has died or BUG " + "found..\n"); + continue; + } + /*overwrite the obsolete 'i' position with the next position*/ + for(j = 3 + i; j < (as_nr + unc_as_nr + 3 - 1); i++) { + poll_fds[j].fd = poll_fds[j + 1].fd; + poll_fds[j].events = poll_fds[j + 1].events; + poll_fds[j].revents = poll_fds[j + 1].revents; + } + close(as->u.as.event_fd); /*close the socket fd*/ + if(as->u.as.ev_buffer.s) { + pkg_free(as->u.as.ev_buffer.s); + as->u.as.ev_buffer.s = (char *)0; + as->u.as.ev_buffer.len = 0; + } + as->u.as.event_fd = as->u.as.action_fd = -1; + as->connected = 0; + destroy_pingtable(&as->u.as.jain_pings); + destroy_pingtable(&as->u.as.servlet_pings); + as_nr--; + LM_WARN("client [%.*s] leaving (Action Dispatcher " + "Process died !)\n", + as->name.len, as->name.s); + break; + } /*if(action_pid==chld)*/ + } /*for(as=as_list;as;as=as->next)*/ + } /*while(waitpid(-1)>0)*/ + } else if(sig_flag) { + LM_WARN("received signal != sigchld(%d)\n", sig_flag); + } + sig_flag = 0; + clean_index = 0; + LM_INFO("polling [2 ServSock] [1 pipe] [%d App Servers]" + " [%d Incomplete AS]\n", + as_nr, unc_as_nr); + poll_events = poll(poll_fds, 3 + unc_as_nr + as_nr, -1); + if(poll_events == -1) { + if(errno == EINTR) { + /*handle the case a child has died. * It will be done in the next iteration in if(seas_sigchld_received)*/ - continue; - } - if(errno==EBADF){ - LM_ERR("invalid file descriptor passed to poll (%s)\n", - strerror(errno)); - return -1;/*??*/ - } - /* errors */ - LM_ERR("poll'ing:%s\n",strerror(errno)); - poll_events=0; - continue; - } else if (poll_events == 0) {/*timeout*/ - continue; - } else {/*there are events !*/ - /*handle connections from server sockets*/ - for(i=0;i<2;i++){ - if(poll_fds[i].revents) - poll_events--; - if(poll_fds[i].revents & POLLIN){ - poll_fds[i].revents &= (~POLLIN); - if((fd=new_as_connect(socks[i],i==0?'e':'a'))>=0){ - poll_tmp=&poll_fds[3+as_nr+unc_as_nr]; - poll_tmp->fd=fd; - poll_tmp->events=POLLIN|POLLHUP; - unc_as_nr++; - LM_DBG("Have new %s client\n",i==0?"event":"action"); - }else{ - LM_ERR("accepting connection from AS\n"); - } - } - } - /*handle data from pipe*/ - if(poll_fds[2].revents & POLLIN){ - poll_fds[2].revents &= (~POLLIN); - poll_events--; - if(dispatch_relay()<0){ - LM_ERR("dispatch_relay returned -1" - "should clean-up table\n"); - } - } - /*now handle receive data from completed AS*/ - clean_index=0; - LM_DBG("Scanning data from %d AS\n",as_nr); - for(i=0;(irevents) - poll_events--; - if(poll_tmp->revents & POLLIN){ - LM_DBG("POLLIN found in AS #%i\n",i); - poll_tmp->revents &= (~POLLIN); - switch(handle_as_data(poll_tmp->fd)){ - case -2:/*read returned 0 bytes, an AS client is leaving*/ - clean_index=1; - break; - case -1:/*shouldnt happen*/ - LM_ERR("reading from AS socket\n"); - break; - case 0:/* event_response received and processed*/ - break; - default: - LM_WARN("unknown return type from handle_as_data\n"); - } - } - if(clean_index || (poll_tmp->revents & POLLHUP)){ - LM_DBG("POLHUP or read==0 found in %i AS \n",i); - clean_index=0; - poll_tmp->revents = 0; - for(as=as_list;as;as=as->next){ - if(as->type==CLUSTER_TYPE) - continue; - if(as->connected && (as->u.as.event_fd == poll_tmp->fd)){ - close(poll_tmp->fd);/*close the socket fd*/ - /*TODO we should send a signal to the Action Dispatcher !!!*/ - as->connected=0; - as_nr--; - /*overwrite the obsolete 'i' position with the next position*/ - for(k=i;k<(as_nr+unc_as_nr);k++){ - j=3+k; - poll_fds[j].fd=poll_fds[j+1].fd; - poll_fds[j].events=poll_fds[j+1].events; - poll_fds[j].revents=poll_fds[j+1].revents; - } - --i; - LM_WARN("client %.*s leaving !!!\n",as->name.len,as->name.s); - break; - } - } - if (!as) { - LM_ERR("the leaving client was not found in the as_list\n"); - } - } - } - /*now handle data sent from incompleted AS*/ - LM_DBG("Scanning data from %d incomplete AS \n",unc_as_nr); - clean_index=0; - for(i=0;irevents) - poll_events--; - if(poll_tmp->revents & POLLIN){ - LM_DBG("POLLIN found in %d incomplete AS \n",i); - poll_tmp->revents &= (~POLLIN); - fd=handle_unc_as_data(poll_tmp->fd); - if(fd>0){ - /* there's a new AS, push the incomplete poll_fds up and set the AS */ - for(k=i;k>0;k--){ - j=3+as_nr+k; - poll_fds[j].fd=poll_fds[j-1].fd; - poll_fds[j].events=poll_fds[j-1].events; - poll_fds[j].revents=poll_fds[j-1].revents; - } - poll_fds[3+as_nr].fd=fd; - poll_fds[3+as_nr].events=POLLIN|POLLHUP; - poll_fds[3+as_nr].revents=0; - as_nr++;/*not very sure if this is thread-safe*/ - unc_as_nr--; - }else if(fd<=0){/* pull the upper set of incomplete AS down and take this one out*/ - poll_tmp->revents=0; - for(k=i;k<(unc_as_nr-1);k++){ - j=3+as_nr+k; - poll_fds[j].fd=poll_fds[j+1].fd; - poll_fds[j].events=poll_fds[j+1].events; - poll_fds[j].revents=poll_fds[j+1].revents; - } - unc_as_nr--; - /** we decrement i so that pulling down the upper part of the unc_as array so that + continue; + } + if(errno == EBADF) { + LM_ERR("invalid file descriptor passed to poll (%s)\n", + strerror(errno)); + return -1; /*??*/ + } + /* errors */ + LM_ERR("poll'ing:%s\n", strerror(errno)); + poll_events = 0; + continue; + } else if(poll_events == 0) { /*timeout*/ + continue; + } else { /*there are events !*/ + /*handle connections from server sockets*/ + for(i = 0; i < 2; i++) { + if(poll_fds[i].revents) + poll_events--; + if(poll_fds[i].revents & POLLIN) { + poll_fds[i].revents &= (~POLLIN); + if((fd = new_as_connect(socks[i], i == 0 ? 'e' : 'a')) + >= 0) { + poll_tmp = &poll_fds[3 + as_nr + unc_as_nr]; + poll_tmp->fd = fd; + poll_tmp->events = POLLIN | POLLHUP; + unc_as_nr++; + LM_DBG("Have new %s client\n", + i == 0 ? "event" : "action"); + } else { + LM_ERR("accepting connection from AS\n"); + } + } + } + /*handle data from pipe*/ + if(poll_fds[2].revents & POLLIN) { + poll_fds[2].revents &= (~POLLIN); + poll_events--; + if(dispatch_relay() < 0) { + LM_ERR("dispatch_relay returned -1" + "should clean-up table\n"); + } + } + /*now handle receive data from completed AS*/ + clean_index = 0; + LM_DBG("Scanning data from %d AS\n", as_nr); + for(i = 0; (i < as_nr) && poll_events; i++) { + clean_index = 0; + poll_tmp = &poll_fds[3 + i]; + if(poll_tmp->revents) + poll_events--; + if(poll_tmp->revents & POLLIN) { + LM_DBG("POLLIN found in AS #%i\n", i); + poll_tmp->revents &= (~POLLIN); + switch(handle_as_data(poll_tmp->fd)) { + case -2: /*read returned 0 bytes, an AS client is leaving*/ + clean_index = 1; + break; + case -1: /*shouldnt happen*/ + LM_ERR("reading from AS socket\n"); + break; + case 0: /* event_response received and processed*/ + break; + default: + LM_WARN("unknown return type from " + "handle_as_data\n"); + } + } + if(clean_index || (poll_tmp->revents & POLLHUP)) { + LM_DBG("POLHUP or read==0 found in %i AS \n", i); + clean_index = 0; + poll_tmp->revents = 0; + for(as = as_list; as; as = as->next) { + if(as->type == CLUSTER_TYPE) + continue; + if(as->connected + && (as->u.as.event_fd == poll_tmp->fd)) { + close(poll_tmp->fd); /*close the socket fd*/ + /*TODO we should send a signal to the Action Dispatcher !!!*/ + as->connected = 0; + as_nr--; + /*overwrite the obsolete 'i' position with the next position*/ + for(k = i; k < (as_nr + unc_as_nr); k++) { + j = 3 + k; + poll_fds[j].fd = poll_fds[j + 1].fd; + poll_fds[j].events = poll_fds[j + 1].events; + poll_fds[j].revents = poll_fds[j + 1].revents; + } + --i; + LM_WARN("client %.*s leaving !!!\n", as->name.len, + as->name.s); + break; + } + } + if(!as) { + LM_ERR("the leaving client was not found in the " + "as_list\n"); + } + } + } + /*now handle data sent from incompleted AS*/ + LM_DBG("Scanning data from %d incomplete AS \n", unc_as_nr); + clean_index = 0; + for(i = 0; i < unc_as_nr && poll_events; i++) { + poll_tmp = &poll_fds[3 + as_nr + i]; + if(poll_tmp->revents) + poll_events--; + if(poll_tmp->revents & POLLIN) { + LM_DBG("POLLIN found in %d incomplete AS \n", i); + poll_tmp->revents &= (~POLLIN); + fd = handle_unc_as_data(poll_tmp->fd); + if(fd > 0) { + /* there's a new AS, push the incomplete poll_fds up and set the AS */ + for(k = i; k > 0; k--) { + j = 3 + as_nr + k; + poll_fds[j].fd = poll_fds[j - 1].fd; + poll_fds[j].events = poll_fds[j - 1].events; + poll_fds[j].revents = poll_fds[j - 1].revents; + } + poll_fds[3 + as_nr].fd = fd; + poll_fds[3 + as_nr].events = POLLIN | POLLHUP; + poll_fds[3 + as_nr].revents = 0; + as_nr++; /*not very sure if this is thread-safe*/ + unc_as_nr--; + } else if( + fd + <= 0) { /* pull the upper set of incomplete AS down and take this one out*/ + poll_tmp->revents = 0; + for(k = i; k < (unc_as_nr - 1); k++) { + j = 3 + as_nr + k; + poll_fds[j].fd = poll_fds[j + 1].fd; + poll_fds[j].events = poll_fds[j + 1].events; + poll_fds[j].revents = poll_fds[j + 1].revents; + } + unc_as_nr--; + /** we decrement i so that pulling down the upper part of the unc_as array so that * it doesn't affect our for loop */ - i--; - } - } - if(poll_tmp->revents & POLLHUP){ - LM_DBG("POLLHUP found in %d incomplete AS \n",i); - close(poll_tmp->fd); - for(k=i;k<(unc_as_nr-1);k++){ - j=3+as_nr+k; - poll_fds[j].fd=poll_fds[j+1].fd; - poll_fds[j].events=poll_fds[j+1].events; - poll_fds[j].revents=poll_fds[j+1].revents; - } - unc_as_nr--; - i--; - poll_tmp->revents = 0; - } - }/*for*/ - }/*else ...(poll_events>0)*/ - }/*while(1)*/ + i--; + } + } + if(poll_tmp->revents & POLLHUP) { + LM_DBG("POLLHUP found in %d incomplete AS \n", i); + close(poll_tmp->fd); + for(k = i; k < (unc_as_nr - 1); k++) { + j = 3 + as_nr + k; + poll_fds[j].fd = poll_fds[j + 1].fd; + poll_fds[j].events = poll_fds[j + 1].events; + poll_fds[j].revents = poll_fds[j + 1].revents; + } + unc_as_nr--; + i--; + poll_tmp->revents = 0; + } + } /*for*/ + } /*else ...(poll_events>0)*/ + } /*while(1)*/ } @@ -352,58 +362,64 @@ int dispatcher_main_loop(void) * returns 0 on exit, <0 on fail * */ -static int open_server_sockets(struct ip_addr *address,unsigned short port,int *fd) +static int open_server_sockets( + struct ip_addr *address, unsigned short port, int *fd) { - /*using sockaddr_union enables ipv6..*/ - union sockaddr_union su; - int i,optval; + /*using sockaddr_union enables ipv6..*/ + union sockaddr_union su; + int i, optval; - fd[0]=fd[1]=-1; + fd[0] = fd[1] = -1; - if(address->af!=AF_INET && address->af!=AF_INET6){ - LM_ERR("Only ip and ipv6 allowed socket types\n"); - return -1; - } + if(address->af != AF_INET && address->af != AF_INET6) { + LM_ERR("Only ip and ipv6 allowed socket types\n"); + return -1; + } - for(i=0;i<2;i++){ - if(init_su(&su,address,port+i)<0){ - LM_ERR("unable to init sockaddr_union\n"); - return -1; - } - if((fd[i]=socket(AF2PF(su.s.sa_family), SOCK_STREAM, 0))==-1){ - LM_ERR("trying to open server %s socket (%s)\n",i==0?"event":"action",strerror(errno)); - goto error; - } - optval=1; - if (setsockopt(fd[i], SOL_SOCKET, SO_REUSEADDR, (void*)&optval, sizeof(optval))==-1) { - LM_ERR("setsockopt (%s)\n",strerror(errno)); - goto error; - } - if ((bind(fd[i],(struct sockaddr *)&(su.s),sizeof(struct sockaddr_in)))==-1){ - LM_ERR( "bind (%s)\n",strerror(errno)); - goto error; - } - if (listen(fd[i], 10)==-1){ - LM_ERR( "listen (%s)\n",strerror(errno)); - goto error; - } - } - return 0; + for(i = 0; i < 2; i++) { + if(init_su(&su, address, port + i) < 0) { + LM_ERR("unable to init sockaddr_union\n"); + return -1; + } + if((fd[i] = socket(AF2PF(su.s.sa_family), SOCK_STREAM, 0)) == -1) { + LM_ERR("trying to open server %s socket (%s)\n", + i == 0 ? "event" : "action", strerror(errno)); + goto error; + } + optval = 1; + if(setsockopt(fd[i], SOL_SOCKET, SO_REUSEADDR, (void *)&optval, + sizeof(optval)) + == -1) { + LM_ERR("setsockopt (%s)\n", strerror(errno)); + goto error; + } + if((bind(fd[i], (struct sockaddr *)&(su.s), sizeof(struct sockaddr_in))) + == -1) { + LM_ERR("bind (%s)\n", strerror(errno)); + goto error; + } + if(listen(fd[i], 10) == -1) { + LM_ERR("listen (%s)\n", strerror(errno)); + goto error; + } + } + return 0; error: - for(i=0;i<2;i++) - if(fd[i]!=-1){ - close(fd[i]); - fd[i]=-1; - } - return -1; + for(i = 0; i < 2; i++) + if(fd[i] != -1) { + close(fd[i]); + fd[i] = -1; + } + return -1; } -union helper{ - as_msg_p ptr; - char bytes[sizeof(as_msg_p)]; +union helper +{ + as_msg_p ptr; + char bytes[sizeof(as_msg_p)]; }; /** @@ -419,93 +435,98 @@ union helper{ */ static int dispatch_relay(void) { - int i,j,retval,tries; - union helper thepointer; + int i, j, retval, tries; + union helper thepointer; - i=j=0; - retval=0; + i = j = 0; + retval = 0; read_again: - i=read(read_pipe,thepointer.bytes+j,sizeof(as_msg_p)-j); - if(i<0){ - if(errno==EINTR){ - goto read_again; - }else{ - LM_ERR("Dispatcher Process received unknown error" - " reading from pipe (%s)\n",strerror(errno)); - retval=-1; - goto error; - } - }else if(i==0){ - LM_ERR("Dispatcher Process " - "received 0 while reading from pipe\n"); - goto error; - }else{ - j+=i; - if(jtransaction) - event_stat(thepointer.ptr->transaction); - if(thepointer.ptr->as == NULL || !thepointer.ptr->as->connected || thepointer.ptr->as->type==CLUSTER_TYPE){ - LM_WARN("tried to send an event to an App Server" - " that is scheduled to die!!\n"); - retval=-2; - goto error; - } - j=0; - tries=0; + if(!thepointer.ptr) { + LM_ERR("Received Corrupted pointer to event !!\n"); + retval = 0; + goto error; + } + /*the message*/ + if(use_stats && thepointer.ptr->transaction) + event_stat(thepointer.ptr->transaction); + if(thepointer.ptr->as == NULL || !thepointer.ptr->as->connected + || thepointer.ptr->as->type == CLUSTER_TYPE) { + LM_WARN("tried to send an event to an App Server" + " that is scheduled to die!!\n"); + retval = -2; + goto error; + } + j = 0; + tries = 0; write_again: - i=write(thepointer.ptr->as->u.as.event_fd,thepointer.ptr->msg+j,thepointer.ptr->len-j); - if(i==-1){ - switch(errno){ - case EINTR: - if(!thepointer.ptr->as->connected){ - LM_WARN("tried to send an event to an App Server" - " that is scheduled to die!!\n"); - retval=-2; - goto error; - } - goto write_again; - case EPIPE: - LM_ERR("AS [%.*s] closed " - "the socket !\n",thepointer.ptr->as->u.as.name.len,thepointer.ptr->as->u.as.name.s); - retval=-2; - goto error; - default: - LM_ERR("unknown error while trying to write to AS socket(%s)\n", - strerror(errno)); - retval=-2; - goto error; - } - }else if(i>0){ - j+=i; - if(jlen) - goto write_again; - }else if(i==0){ - if (tries++ > MAX_WRITE_TRIES) { - LM_ERR("MAX WRITE TRIES !!!\n"); - goto error; - }else - goto write_again; - } - LM_DBG("Event relaied to %.*s AS\n",thepointer.ptr->as->u.as.name.len, - thepointer.ptr->as->u.as.name.s); - LM_DBG("Event type %s \n",action_names[thepointer.ptr->type]); - retval=0; + i = write(thepointer.ptr->as->u.as.event_fd, thepointer.ptr->msg + j, + thepointer.ptr->len - j); + if(i == -1) { + switch(errno) { + case EINTR: + if(!thepointer.ptr->as->connected) { + LM_WARN("tried to send an event to an App Server" + " that is scheduled to die!!\n"); + retval = -2; + goto error; + } + goto write_again; + case EPIPE: + LM_ERR("AS [%.*s] closed " + "the socket !\n", + thepointer.ptr->as->u.as.name.len, + thepointer.ptr->as->u.as.name.s); + retval = -2; + goto error; + default: + LM_ERR("unknown error while trying to write to AS socket(%s)\n", + strerror(errno)); + retval = -2; + goto error; + } + } else if(i > 0) { + j += i; + if(j < thepointer.ptr->len) + goto write_again; + } else if(i == 0) { + if(tries++ > MAX_WRITE_TRIES) { + LM_ERR("MAX WRITE TRIES !!!\n"); + goto error; + } else + goto write_again; + } + LM_DBG("Event relaied to %.*s AS\n", thepointer.ptr->as->u.as.name.len, + thepointer.ptr->as->u.as.name.s); + LM_DBG("Event type %s \n", action_names[thepointer.ptr->type]); + retval = 0; error: - if(thepointer.ptr){ - if(thepointer.ptr->msg) - shm_free(thepointer.ptr->msg); - shm_free(thepointer.ptr); - } - return retval; + if(thepointer.ptr) { + if(thepointer.ptr->msg) + shm_free(thepointer.ptr->msg); + shm_free(thepointer.ptr); + } + return retval; } /** @@ -516,88 +537,91 @@ static int dispatch_relay(void) * 0 on success * -1 on error */ -static inline int add_new_as(int event_idx,int action_idx,struct as_entry *as) +static inline int add_new_as(int event_idx, int action_idx, struct as_entry *as) { - struct unc_as *ev,*ac; - int j; - as_p the_as=0; - struct as_entry *tmp; + struct unc_as *ev, *ac; + int j; + as_p the_as = 0; + struct as_entry *tmp; - ev=&unc_as_t[event_idx]; - ac=&unc_as_t[action_idx]; + ev = &unc_as_t[event_idx]; + ac = &unc_as_t[action_idx]; - the_as=&(as->u.as); + the_as = &(as->u.as); - the_as->action_fd=ac->fd; - the_as->event_fd=ev->fd; - the_as->name.len = strlen(ev->name); - if(use_ha){ - if(jain_ping_timeout){ - if (0>init_pingtable(&the_as->jain_pings,jain_ping_timeout,(jain_ping_timeout/jain_ping_period+1)*PING_OVER_FACTOR)){ - LM_ERR("Unable to init jain pinging table...\n"); - goto error; - } - } - if(servlet_ping_timeout){ - if (0>init_pingtable(&the_as->servlet_pings,servlet_ping_timeout,(servlet_ping_timeout/servlet_ping_period+1)*PING_OVER_FACTOR)){ - LM_ERR("Unable to init servlet pinging table...\n"); - goto error; - } - } - } - /*TODO attention, this is pkg_malloc because only the Event_Dispatcher process + the_as->action_fd = ac->fd; + the_as->event_fd = ev->fd; + the_as->name.len = strlen(ev->name); + if(use_ha) { + if(jain_ping_timeout) { + if(0 > init_pingtable(&the_as->jain_pings, jain_ping_timeout, + (jain_ping_timeout / jain_ping_period + 1) + * PING_OVER_FACTOR)) { + LM_ERR("Unable to init jain pinging table...\n"); + goto error; + } + } + if(servlet_ping_timeout) { + if(0 > init_pingtable(&the_as->servlet_pings, servlet_ping_timeout, + (servlet_ping_timeout / servlet_ping_period + 1) + * PING_OVER_FACTOR)) { + LM_ERR("Unable to init servlet pinging table...\n"); + goto error; + } + } + } + /*TODO attention, this is pkg_malloc because only the Event_Dispatcher process * has to use it !!*/ - if(!(the_as->ev_buffer.s = pkg_malloc(AS_BUF_SIZE))){ - LM_ERR("unable to alloc pkg mem for the event buffer\n"); - goto error; - } - the_as->ev_buffer.len=0; - as->connected=1; - the_as->action_pid=0; - for(tmp=as_list;tmp;tmp=tmp->next){ - if(tmp->type==AS_TYPE) - continue; - for (j=0;ju.cs.num;j++) { - if (tmp->u.cs.as_names[j].len == the_as->name.len && - !memcmp(tmp->u.cs.as_names[j].s,the_as->name.s,the_as->name.len)) { - if(tmp->u.cs.num==tmp->u.cs.registered){ - LM_ERR("AS %.*s belongs to cluster %.*s which is already completed\n", - the_as->name.len,the_as->name.s,tmp->name.len,tmp->name.s); - break; - } - tmp->u.cs.registered++; - break; - } - } - } - if(0>spawn_action_dispatcher(as)){ - LM_ERR("Unable to spawn Action Dispatcher for as %s\n",ev->name); - goto error; - } - if(send_sockinfo(the_as->event_fd)==-1){ - LM_ERR("Unable to send socket info to as %s\n",ev->name); - goto error; - } - return 0; + if(!(the_as->ev_buffer.s = pkg_malloc(AS_BUF_SIZE))) { + LM_ERR("unable to alloc pkg mem for the event buffer\n"); + goto error; + } + the_as->ev_buffer.len = 0; + as->connected = 1; + the_as->action_pid = 0; + for(tmp = as_list; tmp; tmp = tmp->next) { + if(tmp->type == AS_TYPE) + continue; + for(j = 0; j < tmp->u.cs.num; j++) { + if(tmp->u.cs.as_names[j].len == the_as->name.len + && !memcmp(tmp->u.cs.as_names[j].s, the_as->name.s, + the_as->name.len)) { + if(tmp->u.cs.num == tmp->u.cs.registered) { + LM_ERR("AS %.*s belongs to cluster %.*s which is already " + "completed\n", + the_as->name.len, the_as->name.s, tmp->name.len, + tmp->name.s); + break; + } + tmp->u.cs.registered++; + break; + } + } + } + if(0 > spawn_action_dispatcher(as)) { + LM_ERR("Unable to spawn Action Dispatcher for as %s\n", ev->name); + goto error; + } + if(send_sockinfo(the_as->event_fd) == -1) { + LM_ERR("Unable to send socket info to as %s\n", ev->name); + goto error; + } + return 0; error: - if(the_as->ev_buffer.s){ - pkg_free(the_as->ev_buffer.s); - the_as->ev_buffer.s=(char*)0; - } - if(the_as->action_pid) - kill(the_as->action_pid,SIGTERM); - if(jain_ping_timeout) - destroy_pingtable(&the_as->jain_pings); - if(servlet_ping_timeout) - destroy_pingtable(&the_as->servlet_pings); - return -1; + if(the_as->ev_buffer.s) { + pkg_free(the_as->ev_buffer.s); + the_as->ev_buffer.s = (char *)0; + } + if(the_as->action_pid) + kill(the_as->action_pid, SIGTERM); + if(jain_ping_timeout) + destroy_pingtable(&the_as->jain_pings); + if(servlet_ping_timeout) + destroy_pingtable(&the_as->servlet_pings); + return -1; } - - - - /**prints available sockets in SER to the App Server. * format is: * 1: transport identifier (u for UDP, t for TCP, s for TLS) @@ -613,48 +637,52 @@ static inline int add_new_as(int event_idx,int action_idx,struct as_entry *as) */ static inline int send_sockinfo(int fd) { - struct socket_info *s; - unsigned char i; - char buffer[300]; - int k=0,j; - buffer[k++]=16;/*This used to be T_TABLE_POWER in Kamailio 1.0.1, now it is hardcoded in config.h*/ - for(i=0,s=udp_listen;s;s=s->next,i++); + struct socket_info *s; + unsigned char i; + char buffer[300]; + int k = 0, j; + buffer[k++] = + 16; /*This used to be T_TABLE_POWER in Kamailio 1.0.1, now it is hardcoded in config.h*/ + for(i = 0, s = udp_listen; s; s = s->next, i++) + ; #ifdef USE_TCP - for(s=tcp_listen;s;s=s->next,i++); + for(s = tcp_listen; s; s = s->next, i++) + ; #endif #ifdef USE_TLS - for(s=tls_listen;s;s=s->next,i++); + for(s = tls_listen; s; s = s->next, i++) + ; #endif - if(i==0){ - LM_ERR("no udp|tcp|tls sockets ?!!\n"); - return -1; - } - buffer[k++]=i; - for(s=udp_listen;s;s=s->next){ - if(print_sock_info(buffer,300,&k,s,PROTO_UDP)==-1) - return -1; - } + if(i == 0) { + LM_ERR("no udp|tcp|tls sockets ?!!\n"); + return -1; + } + buffer[k++] = i; + for(s = udp_listen; s; s = s->next) { + if(print_sock_info(buffer, 300, &k, s, PROTO_UDP) == -1) + return -1; + } #ifdef USE_TCP - for(s=tcp_listen;s;s=s->next){ - if(print_sock_info(buffer,300,&k,s,PROTO_TCP)==-1) - return -1; - } + for(s = tcp_listen; s; s = s->next) { + if(print_sock_info(buffer, 300, &k, s, PROTO_TCP) == -1) + return -1; + } #endif #ifdef USE_TLS - for(s=tls_listen;s;s=s->next){ - if(print_sock_info(buffer,300,&k,s,PROTO_TLS)==-1) - return -1; - } + for(s = tls_listen; s; s = s->next) { + if(print_sock_info(buffer, 300, &k, s, PROTO_TLS) == -1) + return -1; + } #endif write_again: - j=write(fd,buffer,k); - if(j==-1){ - if(errno==EINTR) - goto write_again; - else - return -1; - } - return 0; + j = write(fd, buffer, k); + if(j == -1) { + if(errno == EINTR) + goto write_again; + else + return -1; + } + return 0; } /* prints sock info into the byte array where @@ -669,31 +697,32 @@ static inline int send_sockinfo(int fd) * * TODO buffer overflow risk */ -static inline int print_sock_info(char *buffer,int wheremax,int *idx,struct socket_info *s,enum sip_protos type) +static inline int print_sock_info(char *buffer, int wheremax, int *idx, + struct socket_info *s, enum sip_protos type) { - int k; - unsigned char i; - unsigned short int j; - if((wheremax-*idx)<49)/*31*name+17*ipv6+2*port+1*type*/ - return -1; - k=*idx; - buffer[k++]=(char)type; - if((i=(unsigned char)s->name.len)>30){ - LM_ERR("name too long\n"); - return -1; - } - buffer[k++]=i; - memcpy(&buffer[k],s->name.s,i); - k+=i; - i=(unsigned char)s->address_str.len; - buffer[k++]=i; - memcpy(&buffer[k],s->address_str.s,i); - k+=i; - j=htons(s->port_no); - memcpy(&buffer[k],&j,2); - k+=2; - *idx=k; - return 0; + int k; + unsigned char i; + unsigned short int j; + if((wheremax - *idx) < 49) /*31*name+17*ipv6+2*port+1*type*/ + return -1; + k = *idx; + buffer[k++] = (char)type; + if((i = (unsigned char)s->name.len) > 30) { + LM_ERR("name too long\n"); + return -1; + } + buffer[k++] = i; + memcpy(&buffer[k], s->name.s, i); + k += i; + i = (unsigned char)s->address_str.len; + buffer[k++] = i; + memcpy(&buffer[k], s->address_str.s, i); + k += i; + j = htons(s->port_no); + memcpy(&buffer[k], &j, 2); + k += 2; + *idx = k; + return 0; } /** @@ -709,32 +738,32 @@ static inline int print_sock_info(char *buffer,int wheremax,int *idx,struct sock */ static int handle_as_data(int fd) { - int j,k; - struct as_entry *as; - for(as=as_list;as;as=as->next) - if(as->type == AS_TYPE && as->connected && (as->u.as.event_fd==fd)) - break; - if(!as){ - LM_ERR("AS not found\n"); - return -1; - } - k=AS_BUF_SIZE-(as->u.as.ev_buffer.len); + int j, k; + struct as_entry *as; + for(as = as_list; as; as = as->next) + if(as->type == AS_TYPE && as->connected && (as->u.as.event_fd == fd)) + break; + if(!as) { + LM_ERR("AS not found\n"); + return -1; + } + k = AS_BUF_SIZE - (as->u.as.ev_buffer.len); again: - if((j=read(fd,as->u.as.ev_buffer.s+as->u.as.ev_buffer.len,k))<0){ - LM_ERR("reading data for as %.*s\n",as->name.len,as->name.s); - if(errno==EINTR) - goto again; - else - return -1; - }else if(j==0){ - LM_ERR("AS client leaving (%.*s)\n",as->name.len,as->name.s); - return -2; - } - as->u.as.ev_buffer.len+=j; - LM_DBG("read %d bytes from AS (total = %d)\n",j,as->u.as.ev_buffer.len); - if(as->u.as.ev_buffer.len>10) - process_event_reply(&as->u.as); - return 0; + if((j = read(fd, as->u.as.ev_buffer.s + as->u.as.ev_buffer.len, k)) < 0) { + LM_ERR("reading data for as %.*s\n", as->name.len, as->name.s); + if(errno == EINTR) + goto again; + else + return -1; + } else if(j == 0) { + LM_ERR("AS client leaving (%.*s)\n", as->name.len, as->name.s); + return -2; + } + as->u.as.ev_buffer.len += j; + LM_DBG("read %d bytes from AS (total = %d)\n", j, as->u.as.ev_buffer.len); + if(as->u.as.ev_buffer.len > 10) + process_event_reply(&as->u.as); + return 0; } /** @@ -760,54 +789,65 @@ static int handle_as_data(int fd) */ static int process_event_reply(as_p as) { - unsigned int ev_len; - unsigned char processor_id,type; - unsigned int flags; + unsigned int ev_len; + unsigned char processor_id, type; + unsigned int flags; - ev_len=(as->ev_buffer.s[0]<<24)|(as->ev_buffer.s[1]<<16)|(as->ev_buffer.s[2]<<8)|((as->ev_buffer.s[3])&0xFF); - type=as->ev_buffer.s[4]; - processor_id=as->ev_buffer.s[5]; - flags=(as->ev_buffer.s[6]<<24)|(as->ev_buffer.s[7]<<16)|(as->ev_buffer.s[8]<<8)|((as->ev_buffer.s[9])&0xFF); - - /*if ev_len > BUF_SIZE then a flag should be put on the AS so that the whole length + ev_len = (as->ev_buffer.s[0] << 24) | (as->ev_buffer.s[1] << 16) + | (as->ev_buffer.s[2] << 8) | ((as->ev_buffer.s[3]) & 0xFF); + type = as->ev_buffer.s[4]; + processor_id = as->ev_buffer.s[5]; + flags = (as->ev_buffer.s[6] << 24) | (as->ev_buffer.s[7] << 16) + | (as->ev_buffer.s[8] << 8) | ((as->ev_buffer.s[9]) & 0xFF); + + /*if ev_len > BUF_SIZE then a flag should be put on the AS so that the whole length * of the action is skipped, until a mechanism for handling big packets is implemented*/ - if(ev_len>AS_BUF_SIZE){ - LM_WARN("Packet too big (%d)!!! should be skipped" - " and an error returned!\n",ev_len); - return -1; - } - if((as->ev_buffer.lenev_buffer.len<4) - return 0; + if(ev_len > AS_BUF_SIZE) { + LM_WARN("Packet too big (%d)!!! should be skipped" + " and an error returned!\n", + ev_len); + return -1; + } + if((as->ev_buffer.len < ev_len) || as->ev_buffer.len < 4) + return 0; - while (as->ev_buffer.len>=ev_len) { - switch(type){ - case BIND_AC: - LM_DBG("Processing a BIND action from AS (length=%d): %.*s\n", - ev_len,as->name.len,as->name.s); - process_bind_action(as,processor_id,flags,&as->ev_buffer.s[10],ev_len-10); - break; - case UNBIND_AC: - LM_DBG("Processing an UNBIND action from AS (length=%d): %.*s\n", - ev_len,as->name.len,as->name.s); - process_unbind_action(as,processor_id,flags,&as->ev_buffer.s[10],ev_len-10); - break; - default: - LM_DBG("Unknown action type %d (len=%d,proc=%d,flags=%d)\n",type,ev_len,(int)processor_id,flags); - return 0; - } - memmove(as->ev_buffer.s,&(as->ev_buffer.s[ev_len]),(as->ev_buffer.len)-ev_len); - (as->ev_buffer.len)-=ev_len; - if(as->ev_buffer.len>10){ - ev_len=(as->ev_buffer.s[0]<<24)|(as->ev_buffer.s[1]<<16)|(as->ev_buffer.s[2]<<8)|((as->ev_buffer.s[3])&0xFF); - type=as->ev_buffer.s[4]; - processor_id=as->ev_buffer.s[5]; - flags=(as->ev_buffer.s[6]<<24)|(as->ev_buffer.s[7]<<16)|(as->ev_buffer.s[8]<<8)|((as->ev_buffer.s[9])&0xFF); - }else{ - return 0; - } - } + while(as->ev_buffer.len >= ev_len) { + switch(type) { + case BIND_AC: + LM_DBG("Processing a BIND action from AS (length=%d): %.*s\n", + ev_len, as->name.len, as->name.s); + process_bind_action(as, processor_id, flags, + &as->ev_buffer.s[10], ev_len - 10); + break; + case UNBIND_AC: + LM_DBG("Processing an UNBIND action from AS (length=%d): " + "%.*s\n", + ev_len, as->name.len, as->name.s); + process_unbind_action(as, processor_id, flags, + &as->ev_buffer.s[10], ev_len - 10); + break; + default: + LM_DBG("Unknown action type %d (len=%d,proc=%d,flags=%d)\n", + type, ev_len, (int)processor_id, flags); + return 0; + } + memmove(as->ev_buffer.s, &(as->ev_buffer.s[ev_len]), + (as->ev_buffer.len) - ev_len); + (as->ev_buffer.len) -= ev_len; + if(as->ev_buffer.len > 10) { + ev_len = (as->ev_buffer.s[0] << 24) | (as->ev_buffer.s[1] << 16) + | (as->ev_buffer.s[2] << 8) + | ((as->ev_buffer.s[3]) & 0xFF); + type = as->ev_buffer.s[4]; + processor_id = as->ev_buffer.s[5]; + flags = (as->ev_buffer.s[6] << 24) | (as->ev_buffer.s[7] << 16) + | (as->ev_buffer.s[8] << 8) | ((as->ev_buffer.s[9]) & 0xFF); + } else { + return 0; + } + } - return 0; + return 0; } @@ -821,69 +861,72 @@ static int process_event_reply(as_p as) * 2:NBO port * */ -int process_bind_action(as_p as,unsigned char processor_id,unsigned int flags,char *payload,int len) +int process_bind_action(as_p as, unsigned char processor_id, unsigned int flags, + char *payload, int len) { - struct socket_info *si,*xxx_listen; - struct ip_addr my_addr; - int i,k,proto; - unsigned short port; - char buffer[300],*proto_s; - k=0; - *buffer=0; - proto_s="NONE"; - for(i=0;ibound_processor[i]==0) - break; - } - if(i==MAX_BINDS){ - LM_ERR("No more bindings allowed. Ignoring bind request for processor %d\n",processor_id); - return -1; - } - memset(&my_addr,0,sizeof(struct ip_addr)); - my_addr.af=payload[k++]; - my_addr.len=payload[k++]; - memcpy(my_addr.u.addr,payload+k,my_addr.len); - k+=my_addr.len; - proto=payload[k++]; - memcpy(&port,payload+k,2); - k+=2; - port=ntohs(port); - ip_addr2sbuf(&my_addr,buffer,300); - switch(proto){ - case PROTO_UDP: - proto_s="UDP"; - xxx_listen=udp_listen; - break; + struct socket_info *si, *xxx_listen; + struct ip_addr my_addr; + int i, k, proto; + unsigned short port; + char buffer[300], *proto_s; + k = 0; + *buffer = 0; + proto_s = "NONE"; + for(i = 0; i < MAX_BINDS; i++) { + if(as->bound_processor[i] == 0) + break; + } + if(i == MAX_BINDS) { + LM_ERR("No more bindings allowed. Ignoring bind request for processor " + "%d\n", + processor_id); + return -1; + } + memset(&my_addr, 0, sizeof(struct ip_addr)); + my_addr.af = payload[k++]; + my_addr.len = payload[k++]; + memcpy(my_addr.u.addr, payload + k, my_addr.len); + k += my_addr.len; + proto = payload[k++]; + memcpy(&port, payload + k, 2); + k += 2; + port = ntohs(port); + ip_addr2sbuf(&my_addr, buffer, 300); + switch(proto) { + case PROTO_UDP: + proto_s = "UDP"; + xxx_listen = udp_listen; + break; #ifdef USE_TCP - case PROTO_TCP: - proto_s="TCP"; - xxx_listen=tcp_listen; - break; + case PROTO_TCP: + proto_s = "TCP"; + xxx_listen = tcp_listen; + break; #endif #ifdef USE_TLS - case PROTO_TLS: - proto_s="TLS"; - xxx_listen=tls_listen; - break; + case PROTO_TLS: + proto_s = "TLS"; + xxx_listen = tls_listen; + break; #endif - default: - goto error; - } - for(si=xxx_listen;si;si=si->next){ - if(my_addr.af==si->address.af && - my_addr.len==si->address.len && - !memcmp(si->address.u.addr,my_addr.u.addr,my_addr.len) && - port == si->port_no){ - as->binds[i]=si; - as->bound_processor[i]=processor_id; - as->num_binds++; - LM_DBG("AS processor with id: %d bound to %s %s %d\n",processor_id,proto_s,buffer,port); - return 0; - } - } + default: + goto error; + } + for(si = xxx_listen; si; si = si->next) { + if(my_addr.af == si->address.af && my_addr.len == si->address.len + && !memcmp(si->address.u.addr, my_addr.u.addr, my_addr.len) + && port == si->port_no) { + as->binds[i] = si; + as->bound_processor[i] = processor_id; + as->num_binds++; + LM_DBG("AS processor with id: %d bound to %s %s %d\n", processor_id, + proto_s, buffer, port); + return 0; + } + } error: - LM_ERR("Cannot bind to %s %s %d !!!\n",proto_s,buffer,port); - return -1; + LM_ERR("Cannot bind to %s %s %d !!!\n", proto_s, buffer, port); + return -1; } /** @@ -892,22 +935,24 @@ int process_bind_action(as_p as,unsigned char processor_id,unsigned int flags,ch * 1:processor_id * */ -int process_unbind_action(as_p as,unsigned char processor_id,unsigned int flags,char *payload,int len) +int process_unbind_action(as_p as, unsigned char processor_id, + unsigned int flags, char *payload, int len) { - int i; + int i; - for(i=0;inum_binds;i++){ - if(as->bound_processor[i] == processor_id) - break; - } - if(i==MAX_BINDS){ - LM_ERR("tried to unbind a processor which is not registered (id=%d)!\n",processor_id); - return 0; - } - as->bound_processor[i]=0; - as->num_binds--; - LM_DBG("AS processor un-bound with id: %d\n",processor_id); - return 0; + for(i = 0; i < as->num_binds; i++) { + if(as->bound_processor[i] == processor_id) + break; + } + if(i == MAX_BINDS) { + LM_ERR("tried to unbind a processor which is not registered (id=%d)!\n", + processor_id); + return 0; + } + as->bound_processor[i] = 0; + as->num_binds--; + LM_DBG("AS processor un-bound with id: %d\n", processor_id); + return 0; } /** @@ -921,78 +966,82 @@ int process_unbind_action(as_p as,unsigned char processor_id,unsigned int flags, */ static int handle_unc_as_data(int fd) { - int i,j,k,len; - char *name1; - struct as_entry *as; - /*first, we see if the data to read is from any of the incompleted as's*/ - for(i=0;i<2*MAX_UNC_AS_NR ;i++) - if(unc_as_t[i].valid && unc_as_t[i].fd==fd) - break; - if(i==2*MAX_UNC_AS_NR){ - LM_ERR("has received an fd which is not in incompleted AS array\n"); - return -1; - } - if(unc_as_t[i].flags & HAS_NAME){/*shouldn't happen, if it has a name, it shouldnt be in fdset[]*/ - LM_WARN("this shouldn't happen\n"); - return 0;/*already have a name, please take me out the incompleted AS array*/ - } - LM_DBG("Reading client name\n"); + int i, j, k, len; + char *name1; + struct as_entry *as; + /*first, we see if the data to read is from any of the incompleted as's*/ + for(i = 0; i < 2 * MAX_UNC_AS_NR; i++) + if(unc_as_t[i].valid && unc_as_t[i].fd == fd) + break; + if(i == 2 * MAX_UNC_AS_NR) { + LM_ERR("has received an fd which is not in incompleted AS array\n"); + return -1; + } + if(unc_as_t[i].flags + & HAS_NAME) { /*shouldn't happen, if it has a name, it shouldnt be in fdset[]*/ + LM_WARN("this shouldn't happen\n"); + return 0; /*already have a name, please take me out the incompleted AS array*/ + } + LM_DBG("Reading client name\n"); - if(-1==(len=read_name(fd,unc_as_t[i].name,MAX_AS_NAME))){ - /*this guy should be disconnected, it sent an AS_NAME too long*/ - LM_ERR("Bad name passed from fd\n"); - unc_as_t[i].valid=0; - unc_as_t[i].flags=0; - return -2; - }else if(len==-2){ - LM_WARN("client disconnected\n"); - return -2; - } - name1=unc_as_t[i].name; + if(-1 == (len = read_name(fd, unc_as_t[i].name, MAX_AS_NAME))) { + /*this guy should be disconnected, it sent an AS_NAME too long*/ + LM_ERR("Bad name passed from fd\n"); + unc_as_t[i].valid = 0; + unc_as_t[i].flags = 0; + return -2; + } else if(len == -2) { + LM_WARN("client disconnected\n"); + return -2; + } + name1 = unc_as_t[i].name; - /* Check the name isn't already taken */ - for(as=as_list;as;as=as->next){ - if(as->name.len==len && !memcmp(name1,as->name.s,len)){ - if(as->connected){ - LM_WARN("AppServer trying to connect with a name already taken (%.*s)\n",len,name1); - unc_as_t[i].valid=0; - unc_as_t[i].flags=0; - return -2; - } - break; - } - } - if (!as) { - LM_ERR("a client tried to connect which is not declared in config. script(%.*s)\n",len,name1); - unc_as_t[i].valid=0; - unc_as_t[i].flags=0; - return -2; - } - unc_as_t[i].flags |= HAS_NAME; - /* the loop's upper bound, + /* Check the name isn't already taken */ + for(as = as_list; as; as = as->next) { + if(as->name.len == len && !memcmp(name1, as->name.s, len)) { + if(as->connected) { + LM_WARN("AppServer trying to connect with a name already taken " + "(%.*s)\n", + len, name1); + unc_as_t[i].valid = 0; + unc_as_t[i].flags = 0; + return -2; + } + break; + } + } + if(!as) { + LM_ERR("a client tried to connect which is not declared in config. " + "script(%.*s)\n", + len, name1); + unc_as_t[i].valid = 0; + unc_as_t[i].flags = 0; + return -2; + } + unc_as_t[i].flags |= HAS_NAME; + /* the loop's upper bound, * if 'i' is in the lower part, then look for an unc_as in the upper part*/ - k=(i>=MAX_UNC_AS_NR?MAX_UNC_AS_NR:2*MAX_UNC_AS_NR); - /* the loop's lower bound */ - for(j=(i>=MAX_UNC_AS_NR?0:MAX_UNC_AS_NR);j= MAX_UNC_AS_NR ? MAX_UNC_AS_NR : 2 * MAX_UNC_AS_NR); + /* the loop's lower bound */ + for(j = (i >= MAX_UNC_AS_NR ? 0 : MAX_UNC_AS_NR); j < k; j++) + if(unc_as_t[j].valid && (unc_as_t[j].flags & HAS_NAME) + && !strcmp(unc_as_t[i].name, unc_as_t[j].name)) + break; + LM_INFO("Fantastic, we have a new client: %s\n", unc_as_t[i].name); + if(j == k) /* the unc_as peer's socket hasn't been found, just take this one out of fdset because it already has its name */ + return 0; /*take me out from fdset[]*/ + LM_INFO("EUREKA, we have a new completed AS: %s\n", unc_as_t[i].name); + /* EUREKA ! we have a sweet pair of AS sockets, with the same name !!*/ + if(add_new_as(i < j ? i : j, i < j ? j : i, as) == -1) { + close(unc_as_t[j].fd); + close(unc_as_t[i].fd); + unc_as_t[j].valid = unc_as_t[i].valid = 0; + unc_as_t[j].flags = unc_as_t[i].flags = 0; + return -1; + } + unc_as_t[j].valid = unc_as_t[i].valid = 0; + unc_as_t[j].flags = unc_as_t[i].flags = 0; + return unc_as_t[i < j ? i : j].fd; } @@ -1000,40 +1049,42 @@ static int handle_unc_as_data(int fd) * socket and copies it into dst, then returns strlen(dst) * or -1 if error. */ -static inline int read_name(int sock,char *dst,int dstlen) +static inline int read_name(int sock, char *dst, int dstlen) { - int n,namelen; - namelen=0; + int n, namelen; + namelen = 0; try_again1: - if((n=read(sock,&namelen,1))<0){ - if(errno==EINTR) - goto try_again1; - else{ - LM_ERR("trying to read length from fd=%d (%s)\n",sock,strerror(errno)); - return -1; - } - }else if(n==0){ - LM_WARN("incomplete AS has disconnected before giving its name\n"); - return -2; - } - if(namelen>dstlen || namelen==0){ - LM_ERR("name too long to fit in dst (%d > %d)\n",namelen,dstlen); - return -1; - } + if((n = read(sock, &namelen, 1)) < 0) { + if(errno == EINTR) + goto try_again1; + else { + LM_ERR("trying to read length from fd=%d (%s)\n", sock, + strerror(errno)); + return -1; + } + } else if(n == 0) { + LM_WARN("incomplete AS has disconnected before giving its name\n"); + return -2; + } + if(namelen > dstlen || namelen == 0) { + LM_ERR("name too long to fit in dst (%d > %d)\n", namelen, dstlen); + return -1; + } try_again2: - if((n=read(sock,dst,namelen))<0){ - if(errno==EINTR) - goto try_again2; - else{ - LM_ERR("trying to read %d chars into %p from fd=%d (%s)\n",namelen,dst,sock,strerror(errno)); - return -1; - } - }else if(n==0){ - LM_WARN("incomplete AS has disconnected before giving its name\n"); - return -2; - } - dst[namelen]=0; - return namelen; + if((n = read(sock, dst, namelen)) < 0) { + if(errno == EINTR) + goto try_again2; + else { + LM_ERR("trying to read %d chars into %p from fd=%d (%s)\n", namelen, + dst, sock, strerror(errno)); + return -1; + } + } else if(n == 0) { + LM_WARN("incomplete AS has disconnected before giving its name\n"); + return -2; + } + dst[namelen] = 0; + return namelen; } /* handle new App Server connect. @@ -1049,79 +1100,82 @@ static inline int read_name(int sock,char *dst,int dstlen) * the point is, the connects must allways come in pairs, if one comes alone, we lost sync. * we should put kind of timeout in connects or something... */ -static int new_as_connect(int fd,char which) +static int new_as_connect(int fd, char which) { - union sockaddr_union su; - int sock,i,flags; - socklen_t su_len; + union sockaddr_union su; + int sock, i, flags; + socklen_t su_len; - su_len = sizeof(union sockaddr_union); - sock=-1; + su_len = sizeof(union sockaddr_union); + sock = -1; again: - sock=accept(fd, &su.s, &su_len); - if(sock==-1){ - if(errno==EINTR){ - goto again; - }else{ - LM_ERR("while accepting connection: %s\n", strerror(errno)); - return -1; - } - } - switch(which){ - case 'e': - for(i=0;iname.len,the_as->name.s); - return -1; - } - if(pid==0){/*child*/ - my_as = the_as; - is_dispatcher=0; - dispatch_actions(); - exit(0); - }else{ - the_as->u.as.action_pid=pid; - } - return 0; + pid_t pid; + pid = fork(); + if(pid < 0) { + LM_ERR("unable to fork an action dispatcher for %.*s\n", + the_as->name.len, the_as->name.s); + return -1; + } + if(pid == 0) { /*child*/ + my_as = the_as; + is_dispatcher = 0; + dispatch_actions(); + exit(0); + } else { + the_as->u.as.action_pid = pid; + } + return 0; } - diff --git a/src/modules/seas/event_dispatcher.h b/src/modules/seas/event_dispatcher.h index 368390532b7..e974ae540df 100644 --- a/src/modules/seas/event_dispatcher.h +++ b/src/modules/seas/event_dispatcher.h @@ -22,19 +22,22 @@ #include "../../core/ip_addr.h" -struct unc_as{ - char valid; - int fd; - char name[MAX_AS_NAME]; - char flags; - union sockaddr_union su; +struct unc_as +{ + char valid; + int fd; + char name[MAX_AS_NAME]; + char flags; + union sockaddr_union su; }; /*incomplete as table, from 0 to MAX_UNC_AS_NR are event, from then on are action*/ /*should only be modified by the dispatcher process, or we should add a lock*/ extern struct unc_as unc_as_t[]; -int process_unbind_action(as_p as,unsigned char processor_id,unsigned int flags,char *payload,int len); -int process_bind_action(as_p as,unsigned char processor_id,unsigned int flags,char *payload,int len); +int process_unbind_action(as_p as, unsigned char processor_id, + unsigned int flags, char *payload, int len); +int process_bind_action(as_p as, unsigned char processor_id, unsigned int flags, + char *payload, int len); int dispatcher_main_loop(); int spawn_action_dispatcher(struct as_entry *as); diff --git a/src/modules/seas/ha.c b/src/modules/seas/ha.c index ebaaa042e76..a880ebba9da 100644 --- a/src/modules/seas/ha.c +++ b/src/modules/seas/ha.c @@ -21,31 +21,32 @@ #include /*atoi*/ -#include /*gettimeofday*/ -#include /*poll*/ +#include /*gettimeofday*/ +#include /*poll*/ #include "ha.h" #include "seas.h" -#include "../../core/mem/mem.h" /*pkg_malloc*/ +#include "../../core/mem/mem.h" /*pkg_malloc*/ #include "../../core/mem/shm_mem.h" /*shm_malloc*/ /** if any of these global ping vars is set to 0, then * this kind of ping is DISABLED */ -char *jain_ping_config=0; -int jain_ping_period=0; -int jain_pings_lost=0; -int jain_ping_timeout=0; +char *jain_ping_config = 0; +int jain_ping_period = 0; +int jain_pings_lost = 0; +int jain_ping_timeout = 0; -char *servlet_ping_config=0; -int servlet_ping_period=0; -int servlet_pings_lost=0; -int servlet_ping_timeout=0; +char *servlet_ping_config = 0; +int servlet_ping_period = 0; +int servlet_pings_lost = 0; +int servlet_ping_timeout = 0; -int use_ha=0; +int use_ha = 0; pid_t pinger_pid; -static inline int parse_ping(char * string,int *ping_period,int *pings_lost,int *ping_timeout); -static inline int send_ping(struct as_entry *the_as,struct timeval *now); +static inline int parse_ping( + char *string, int *ping_period, int *pings_lost, int *ping_timeout); +static inline int send_ping(struct as_entry *the_as, struct timeval *now); /** * returns: * 0 if no High Availability @@ -54,53 +55,58 @@ static inline int send_ping(struct as_entry *the_as,struct timeval *now); */ int prepare_ha(void) { - use_ha=0; - if(!(jain_ping_config || servlet_ping_config)){ - jain_pings_lost=servlet_pings_lost=0; - return 0; - } - if(parse_ping(jain_ping_config,&jain_ping_period,&jain_pings_lost,&jain_ping_timeout)<0) - goto error; - if(parse_ping(servlet_ping_config,&servlet_ping_period,&servlet_pings_lost,&servlet_ping_timeout)<0) - goto error; - LM_DBG("jain: pinging period :%d max pings lost:%d ping timeout:%d\n", - jain_ping_period,jain_pings_lost,jain_ping_timeout); - LM_DBG("servlet: pinging period:%d max pings lost:%d ping timeout:%d\n", - servlet_ping_period,servlet_pings_lost,servlet_ping_timeout); - use_ha=1; - return 1; + use_ha = 0; + if(!(jain_ping_config || servlet_ping_config)) { + jain_pings_lost = servlet_pings_lost = 0; + return 0; + } + if(parse_ping(jain_ping_config, &jain_ping_period, &jain_pings_lost, + &jain_ping_timeout) + < 0) + goto error; + if(parse_ping(servlet_ping_config, &servlet_ping_period, + &servlet_pings_lost, &servlet_ping_timeout) + < 0) + goto error; + LM_DBG("jain: pinging period :%d max pings lost:%d ping timeout:%d\n", + jain_ping_period, jain_pings_lost, jain_ping_timeout); + LM_DBG("servlet: pinging period:%d max pings lost:%d ping timeout:%d\n", + servlet_ping_period, servlet_pings_lost, servlet_ping_timeout); + use_ha = 1; + return 1; error: - return -1; + return -1; } -int print_pingtable(struct ha *ta,int idx,int lock) +int print_pingtable(struct ha *ta, int idx, int lock) { - int i; - if(lock) - lock_get(ta->mutex); - for(i=0;isize;i++){ - if((ta->begin+ta->count)>ta->size){ - if ((ibegin && i<((ta->begin+ta->count)%ta->size)) || (i>=ta->begin && i<(ta->begin+ta->count))) - fprintf(stderr,"*"); - else - fprintf(stderr,"="); - }else{ - if (i>=ta->begin && i<(ta->begin+ta->count)) - fprintf(stderr,"*"); - else - fprintf(stderr,"="); - } - } - if(lock) - lock_release(ta->mutex); - fprintf(stderr,"\n"); - for(i=0;isize;i++) - if(i==idx) - fprintf(stderr,"-"); - else - fprintf(stderr,"%d",i); - fprintf(stderr,"\n"); - return 0; + int i; + if(lock) + lock_get(ta->mutex); + for(i = 0; i < ta->size; i++) { + if((ta->begin + ta->count) > ta->size) { + if((i < ta->begin && i < ((ta->begin + ta->count) % ta->size)) + || (i >= ta->begin && i < (ta->begin + ta->count))) + fprintf(stderr, "*"); + else + fprintf(stderr, "="); + } else { + if(i >= ta->begin && i < (ta->begin + ta->count)) + fprintf(stderr, "*"); + else + fprintf(stderr, "="); + } + } + if(lock) + lock_release(ta->mutex); + fprintf(stderr, "\n"); + for(i = 0; i < ta->size; i++) + if(i == idx) + fprintf(stderr, "-"); + else + fprintf(stderr, "%d", i); + fprintf(stderr, "\n"); + return 0; } /** @@ -115,48 +121,50 @@ int print_pingtable(struct ha *ta,int idx,int lock) * -1 if config is malformed (unable to parse); * 1 if config is successfully set */ -static inline int parse_ping(char * string,int *ping_period,int *pings_lost,int *ping_timeout) +static inline int parse_ping( + char *string, int *ping_period, int *pings_lost, int *ping_timeout) { - char *ping_period_s,*pings_lost_s,*ping_timeout_s; - ping_period_s=pings_lost_s=ping_timeout_s=(char *)0; + char *ping_period_s, *pings_lost_s, *ping_timeout_s; + ping_period_s = pings_lost_s = ping_timeout_s = (char *)0; - if(string==0 || *string==0){ - *ping_period=0; - *pings_lost=0; - *ping_timeout=0; - return 0; - } + if(string == 0 || *string == 0) { + *ping_period = 0; + *pings_lost = 0; + *ping_timeout = 0; + return 0; + } - if (((*string)<'0')||((*string)>'9')) { - LM_ERR("malformed ping config string. Unparseable :[%s]\n",string); - return -1; - } - ping_period_s=string; - while(*string){ - if(*string == ':'){ - *string=0; - if (!pings_lost_s && (*(string+1))) { - pings_lost_s=string+1; - }else if (!ping_timeout_s && (*(string+1))) { - ping_timeout_s=string+1; - }else{ - LM_ERR("malformed ping config string. Unparseable :[%s]\n",string); - return -1; - } - } - string++; - } - if (!(ping_period_s && pings_lost_s && ping_timeout_s)) { - LM_ERR("malformed ping config string. Unparseable :[%s]\n",string); - return -1; - } - *ping_period =atoi(ping_period_s); - *pings_lost=atoi(pings_lost_s); - *ping_timeout=atoi(ping_timeout_s); - if (*ping_period<=0 || *pings_lost<=0 || *ping_timeout<=0) { - return -1; - } - return 1; + if(((*string) < '0') || ((*string) > '9')) { + LM_ERR("malformed ping config string. Unparseable :[%s]\n", string); + return -1; + } + ping_period_s = string; + while(*string) { + if(*string == ':') { + *string = 0; + if(!pings_lost_s && (*(string + 1))) { + pings_lost_s = string + 1; + } else if(!ping_timeout_s && (*(string + 1))) { + ping_timeout_s = string + 1; + } else { + LM_ERR("malformed ping config string. Unparseable :[%s]\n", + string); + return -1; + } + } + string++; + } + if(!(ping_period_s && pings_lost_s && ping_timeout_s)) { + LM_ERR("malformed ping config string. Unparseable :[%s]\n", string); + return -1; + } + *ping_period = atoi(ping_period_s); + *pings_lost = atoi(pings_lost_s); + *ping_timeout = atoi(ping_timeout_s); + if(*ping_period <= 0 || *pings_lost <= 0 || *ping_timeout <= 0) { + return -1; + } + return 1; } /** @@ -169,75 +177,86 @@ static inline int parse_ping(char * string,int *ping_period,int *pings_lost,int */ int spawn_pinger(void) { - int n,next_jain,next_servlet,timeout; - struct timeval now,last_jain,last_servlet; - struct as_entry *as; + int n, next_jain, next_servlet, timeout; + struct timeval now, last_jain, last_servlet; + struct as_entry *as; - if ((pinger_pid=fork())<0) { - LM_ERR("forking failed!\n"); - goto error; - }else if(pinger_pid>0){ - return 0; - } - strcpy(whoami,"Pinger Process\n"); - is_dispatcher=0; - my_as=0; - /* child */ - if(jain_ping_period && servlet_ping_period){ - next_jain=next_servlet=0; - }else if(jain_ping_period){ - next_servlet=INT_MAX; - next_jain=0; - }else if(servlet_ping_period){ - next_jain=INT_MAX; - next_servlet=0; - }else{ - next_jain=next_servlet=INT_MAX; - } + if((pinger_pid = fork()) < 0) { + LM_ERR("forking failed!\n"); + goto error; + } else if(pinger_pid > 0) { + return 0; + } + strcpy(whoami, "Pinger Process\n"); + is_dispatcher = 0; + my_as = 0; + /* child */ + if(jain_ping_period && servlet_ping_period) { + next_jain = next_servlet = 0; + } else if(jain_ping_period) { + next_servlet = INT_MAX; + next_jain = 0; + } else if(servlet_ping_period) { + next_jain = INT_MAX; + next_servlet = 0; + } else { + next_jain = next_servlet = INT_MAX; + } - gettimeofday(&last_jain,NULL); - memcpy(&last_servlet,&last_jain,sizeof(struct timeval)); + gettimeofday(&last_jain, NULL); + memcpy(&last_servlet, &last_jain, sizeof(struct timeval)); - while(1){ - gettimeofday(&now,NULL); - if(next_jain!=INT_MAX){ - next_jain=jain_ping_period-((now.tv_sec-last_jain.tv_sec)*1000 + (now.tv_usec-last_jain.tv_usec)/1000); - } - if(next_servlet!=INT_MAX){ - next_servlet=servlet_ping_period-((now.tv_sec-last_servlet.tv_sec)*1000 + (now.tv_usec-last_servlet.tv_usec)/1000); - } + while(1) { + gettimeofday(&now, NULL); + if(next_jain != INT_MAX) { + next_jain = jain_ping_period + - ((now.tv_sec - last_jain.tv_sec) * 1000 + + (now.tv_usec - last_jain.tv_usec) / 1000); + } + if(next_servlet != INT_MAX) { + next_servlet = + servlet_ping_period + - ((now.tv_sec - last_servlet.tv_sec) * 1000 + + (now.tv_usec - last_servlet.tv_usec) / 1000); + } - timeout=next_jain=jain_ping_period) { - gettimeofday(&last_jain,NULL); - for(as=as_list;as;as=as->next){ - if(as->type == AS_TYPE && as->connected){ - send_ping(as,&now); - } - } - } - if (servlet_ping_period && ((now.tv_sec-last_servlet.tv_sec)*1000 + (now.tv_usec-last_servlet.tv_usec)/1000)>=servlet_ping_period) { - gettimeofday(&last_servlet,NULL); - for(as=as_list;as;as=as->next){ - if(as->type==AS_TYPE && as->connected){ - send_ping(as,&now); - } - } - } - }else{/*impossible..*/ - LM_ERR("bug:poll returned %d\n",n); - goto error; - } - } - return 0; + if((n = poll(NULL, 0, timeout < 0 ? 0 : timeout)) < 0) { + LM_ERR("poll returned %d\n", n); + goto error; + } else if(n == 0) { /*timeout*/ + gettimeofday(&now, NULL); + if(jain_ping_period + && ((now.tv_sec - last_jain.tv_sec) * 1000 + + (now.tv_usec - last_jain.tv_usec) / 1000) + >= jain_ping_period) { + gettimeofday(&last_jain, NULL); + for(as = as_list; as; as = as->next) { + if(as->type == AS_TYPE && as->connected) { + send_ping(as, &now); + } + } + } + if(servlet_ping_period + && ((now.tv_sec - last_servlet.tv_sec) * 1000 + + (now.tv_usec - last_servlet.tv_usec) / 1000) + >= servlet_ping_period) { + gettimeofday(&last_servlet, NULL); + for(as = as_list; as; as = as->next) { + if(as->type == AS_TYPE && as->connected) { + send_ping(as, &now); + } + } + } + } else { /*impossible..*/ + LM_ERR("bug:poll returned %d\n", n); + goto error; + } + } + return 0; error: - return -1; + return -1; } /** @@ -247,64 +266,65 @@ int spawn_pinger(void) * 0 on success * -1 on error */ -static inline int send_ping(struct as_entry *the_as,struct timeval *now) +static inline int send_ping(struct as_entry *the_as, struct timeval *now) { - char *the_ping; - as_msg_p aping; - int pinglen,retval; - unsigned int seqno; - struct ping *pingu; + char *the_ping; + as_msg_p aping; + int pinglen, retval; + unsigned int seqno; + struct ping *pingu; - aping=(as_msg_p)0; - the_ping=(char *)0; - retval=0; - if (!(aping=shm_malloc(sizeof(as_msg_t)))) { - LM_ERR("out of shm_mem for ping event\n"); - retval=-1; - goto error; - } - if (!(the_ping=create_ping_event(&pinglen,0,&seqno))) { - LM_ERR("Unable to create ping event\n"); - retval=-1; - goto error; - } - aping->as=the_as; - aping->msg=the_ping; - aping->len=pinglen; - - lock_get(the_as->u.as.jain_pings.mutex); - { - if(the_as->u.as.jain_pings.count==the_as->u.as.jain_pings.size){ - LM_ERR("Cant send ping because the pingtable is full (%d pings)\n",\ - the_as->u.as.jain_pings.count); - retval=0; - lock_release(the_as->u.as.jain_pings.mutex); - goto error; - }else{ - pingu=the_as->u.as.jain_pings.pings+the_as->u.as.jain_pings.end; - the_as->u.as.jain_pings.end=(the_as->u.as.jain_pings.end+1)%the_as->u.as.jain_pings.size; - the_as->u.as.jain_pings.count++; - } - memcpy(&pingu->sent,now,sizeof(struct timeval)); - pingu->id=seqno; - } - lock_release(the_as->u.as.jain_pings.mutex); + aping = (as_msg_p)0; + the_ping = (char *)0; + retval = 0; + if(!(aping = shm_malloc(sizeof(as_msg_t)))) { + LM_ERR("out of shm_mem for ping event\n"); + retval = -1; + goto error; + } + if(!(the_ping = create_ping_event(&pinglen, 0, &seqno))) { + LM_ERR("Unable to create ping event\n"); + retval = -1; + goto error; + } + aping->as = the_as; + aping->msg = the_ping; + aping->len = pinglen; + + lock_get(the_as->u.as.jain_pings.mutex); + { + if(the_as->u.as.jain_pings.count == the_as->u.as.jain_pings.size) { + LM_ERR("Cant send ping because the pingtable is full (%d pings)\n", + the_as->u.as.jain_pings.count); + retval = 0; + lock_release(the_as->u.as.jain_pings.mutex); + goto error; + } else { + pingu = the_as->u.as.jain_pings.pings + the_as->u.as.jain_pings.end; + the_as->u.as.jain_pings.end = (the_as->u.as.jain_pings.end + 1) + % the_as->u.as.jain_pings.size; + the_as->u.as.jain_pings.count++; + } + memcpy(&pingu->sent, now, sizeof(struct timeval)); + pingu->id = seqno; + } + lock_release(the_as->u.as.jain_pings.mutex); again: - if(0>write(write_pipe,&aping,sizeof(as_msg_p))){ - if(errno==EINTR){ - goto again; - }else{ - LM_ERR("error sending ping\n"); - goto error; - } - } - return 0; + if(0 > write(write_pipe, &aping, sizeof(as_msg_p))) { + if(errno == EINTR) { + goto again; + } else { + LM_ERR("error sending ping\n"); + goto error; + } + } + return 0; error: - if(aping) - shm_free(aping); - if(the_ping) - shm_free(the_ping); - return retval; + if(aping) + shm_free(aping); + if(the_ping) + shm_free(the_ping); + return retval; } /** @@ -314,44 +334,46 @@ static inline int send_ping(struct as_entry *the_as,struct timeval *now) * 0 on success * -1 on error */ -int init_pingtable(struct ha *table,int timeout,int maxpings) +int init_pingtable(struct ha *table, int timeout, int maxpings) { - if(maxpings<=0) - maxpings=1; - table->begin=0; - table->end=0; - table->timed_out_pings=0; - table->size=maxpings; - table->timeout=timeout; + if(maxpings <= 0) + maxpings = 1; + table->begin = 0; + table->end = 0; + table->timed_out_pings = 0; + table->size = maxpings; + table->timeout = timeout; - if (!(table->mutex=lock_alloc())){ - LM_ERR("Unable to allocate a lock for the ping table\n"); - goto error; - }else - lock_init(table->mutex); - LM_ERR("alloc'ing %d bytes for %d pings\n",(int)(maxpings*sizeof(struct ping)),maxpings); - if (0==(table->pings=shm_malloc(maxpings*sizeof(struct ping)))){ - LM_ERR("Unable to shm_malloc %d bytes for %d pings\n",(int)(maxpings*sizeof(struct ping)),maxpings); - goto error; - }else{ - memset(table->pings,0,(maxpings*sizeof(struct ping))); - } - return 0; + if(!(table->mutex = lock_alloc())) { + LM_ERR("Unable to allocate a lock for the ping table\n"); + goto error; + } else + lock_init(table->mutex); + LM_ERR("alloc'ing %d bytes for %d pings\n", + (int)(maxpings * sizeof(struct ping)), maxpings); + if(0 == (table->pings = shm_malloc(maxpings * sizeof(struct ping)))) { + LM_ERR("Unable to shm_malloc %d bytes for %d pings\n", + (int)(maxpings * sizeof(struct ping)), maxpings); + goto error; + } else { + memset(table->pings, 0, (maxpings * sizeof(struct ping))); + } + return 0; error: - destroy_pingtable(table); - return -1; + destroy_pingtable(table); + return -1; } void destroy_pingtable(struct ha *table) { - if(table->mutex){ - lock_dealloc(table->mutex); - table->mutex=0; - } - if(table->pings){ - shm_free(table->pings); - table->pings=0; - } + if(table->mutex) { + lock_dealloc(table->mutex); + table->mutex = 0; + } + if(table->pings) { + shm_free(table->pings); + table->pings = 0; + } } /** @@ -368,33 +390,33 @@ void destroy_pingtable(struct ha *table) * pointer to the buffer on success * */ -char * create_ping_event(int *evt_len,int flags,unsigned int *seqno) +char *create_ping_event(int *evt_len, int flags, unsigned int *seqno) { - unsigned int i,k; - char *buffer; - static unsigned int ping_seqno=0; + unsigned int i, k; + char *buffer; + static unsigned int ping_seqno = 0; - if (!(buffer=shm_malloc(4+1+1+4+4))) { - LM_ERR("out of shm for ping\n"); - return 0; - } - *evt_len=(4+1+1+4+4); - ping_seqno++; - *seqno=ping_seqno; - i=htonl(14); - memcpy(buffer,&i,4); - k=4; - /*type*/ - buffer[k++]=(unsigned char)PING_AC; - /*processor_id*/ - buffer[k++]=(unsigned char)0xFF; - /*flags*/ - flags=htonl(flags); - memcpy(buffer+k,&flags,4); - k+=4; - /*ping sequence number*/ - i=htonl(ping_seqno); - memcpy(buffer+k,&i,4); - k+=4; - return buffer; + if(!(buffer = shm_malloc(4 + 1 + 1 + 4 + 4))) { + LM_ERR("out of shm for ping\n"); + return 0; + } + *evt_len = (4 + 1 + 1 + 4 + 4); + ping_seqno++; + *seqno = ping_seqno; + i = htonl(14); + memcpy(buffer, &i, 4); + k = 4; + /*type*/ + buffer[k++] = (unsigned char)PING_AC; + /*processor_id*/ + buffer[k++] = (unsigned char)0xFF; + /*flags*/ + flags = htonl(flags); + memcpy(buffer + k, &flags, 4); + k += 4; + /*ping sequence number*/ + i = htonl(ping_seqno); + memcpy(buffer + k, &i, 4); + k += 4; + return buffer; } diff --git a/src/modules/seas/ha.h b/src/modules/seas/ha.h index 7e5f9a47981..dbbd0139e27 100644 --- a/src/modules/seas/ha.h +++ b/src/modules/seas/ha.h @@ -22,23 +22,25 @@ #ifndef HA_H #define HA_H -#include "../../core/locking.h"/* for get_lock_t define*/ +#include "../../core/locking.h" /* for get_lock_t define*/ #include -struct ping{ - unsigned int id; - struct timeval sent; - struct ping *next; +struct ping +{ + unsigned int id; + struct timeval sent; + struct ping *next; }; -struct ha{ - int timed_out_pings; - int timeout; - gen_lock_t *mutex; - struct ping *pings; - int begin; - int end; - int count; - int size; +struct ha +{ + int timed_out_pings; + int timeout; + gen_lock_t *mutex; + struct ping *pings; + int begin; + int end; + int count; + int size; }; extern char *jain_ping_config; @@ -55,10 +57,10 @@ extern struct ping *servlet_pings; extern int use_ha; -char * create_ping_event(int *evt_len,int flags,unsigned int *seqno); +char *create_ping_event(int *evt_len, int flags, unsigned int *seqno); int prepare_ha(void); int spawn_pinger(void); -int print_pingtable(struct ha *ta,int idx,int lock); -int init_pingtable(struct ha *table,int timeout,int maxpings); +int print_pingtable(struct ha *ta, int idx, int lock); +int init_pingtable(struct ha *table, int timeout, int maxpings); void destroy_pingtable(struct ha *table); #endif diff --git a/src/modules/seas/seas.c b/src/modules/seas/seas.c index 303b7beb10c..3c8e17c2673 100644 --- a/src/modules/seas/seas.c +++ b/src/modules/seas/seas.c @@ -18,23 +18,23 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include /*memset*/ -#include /*errno*/ -#include /*close(),pipe,fork,pid_t*/ +#include /*memset*/ +#include /*errno*/ +#include /*close(),pipe,fork,pid_t*/ #include /*wait*/ -#include /*SIGINT,etc*/ +#include /*SIGINT,etc*/ #include "../../core/sr_module.h" -#include "../../core/ip_addr.h" /*ip_addr,hostent2ip_addr*/ -#include "../../core/tags.h" /*init_tags*/ -#include "../../core/socket_info.h" /*get_first_socket()*/ -#include "../../core/resolve.h" /*resolvehost*/ -#include "../../core/mem/mem.h" /*pkg_malloc*/ -#include "../../core/mem/shm_mem.h" /*shm_malloc*/ -#include "../../core/dprint.h" /*LM_**/ -#include "../../core/error.h" /*ser_error*/ -#include "../../modules/tm/tm_load.h" /*load_tm_api*/ -#include "../../modules/tm/h_table.h" /*cell*/ +#include "../../core/ip_addr.h" /*ip_addr,hostent2ip_addr*/ +#include "../../core/tags.h" /*init_tags*/ +#include "../../core/socket_info.h" /*get_first_socket()*/ +#include "../../core/resolve.h" /*resolvehost*/ +#include "../../core/mem/mem.h" /*pkg_malloc*/ +#include "../../core/mem/shm_mem.h" /*shm_malloc*/ +#include "../../core/dprint.h" /*LM_**/ +#include "../../core/error.h" /*ser_error*/ +#include "../../modules/tm/tm_load.h" /*load_tm_api*/ +#include "../../modules/tm/h_table.h" /*cell*/ #include "../../modules/tm/t_lookup.h" /*T_UNDEFINED*/ #include "../../core/cfg/cfg_struct.h" @@ -43,7 +43,7 @@ #include "seas.h" #include "seas_action.h" #include "event_dispatcher.h" -#include "statistics.h"/*pstart_stats_server*/ +#include "statistics.h" /*pstart_stats_server*/ #include "ha.h" #include "cluster.h" @@ -58,106 +58,97 @@ static int w_as_relay_sl(struct sip_msg *msg, char *as_name, char *foo); static int seas_init(void); static int seas_child_init(int rank); static void seas_exit(); -static int fixup_as_relay(void** param, int param_no); +static int fixup_as_relay(void **param, int param_no); /*utility functions*/ static void seas_init_tags(); -static inline int is_e2e_ack(struct cell *t,struct sip_msg *msg); +static inline int is_e2e_ack(struct cell *t, struct sip_msg *msg); -char seas_tags[TOTAG_VALUE_LEN+1]; +char seas_tags[TOTAG_VALUE_LEN + 1]; char *seas_tag_suffix; char whoami[MAX_WHOAMI_LEN]; -int is_dispatcher=0; +int is_dispatcher = 0; extern int sig_flag; -static char *seas_listen_socket=0; -static char *seas_stats_socket=0; +static char *seas_listen_socket = 0; +static char *seas_stats_socket = 0; -struct ip_addr *seas_listen_ip=0; -unsigned short seas_listen_port=0; +struct ip_addr *seas_listen_ip = 0; +unsigned short seas_listen_port = 0; -struct as_entry *as_table=0; +struct as_entry *as_table = 0; -struct as_entry *as_list=0; +struct as_entry *as_list = 0; -int write_pipe=0; -int read_pipe=0; +int write_pipe = 0; +int read_pipe = 0; struct seas_functions seas_f; -static cmd_export_t cmds[]= -{ - {"as_relay_t", (cmd_function)w_as_relay_t, 1, fixup_as_relay, - 0, REQUEST_ROUTE}, - {"as_relay_sl", (cmd_function)w_as_relay_sl, 1, fixup_as_relay, - 0, REQUEST_ROUTE}, - {0,0,0,0,0,0} -}; - -static param_export_t params[]= -{ - {"listen_sockets",PARAM_STRING, &seas_listen_socket}, - {"stats_socket", PARAM_STRING, &seas_stats_socket}, - {"jain_ping", PARAM_STRING, &jain_ping_config}, - {"servlet_ping", PARAM_STRING, &servlet_ping_config}, - {"clusters", PARAM_STRING, &cluster_cfg}, - {0,0,0} -}; - -struct module_exports exports= -{ - "seas", - DEFAULT_DLFLAGS, - cmds, /* exported commands */ - params, /* exported parameters */ - 0, /* exported RPC methods */ - 0, /* exported module-items (pseudo variables) */ - 0, /* response function */ - seas_init, /* module initialization function */ - seas_child_init, /* per-child init function */ - seas_exit /* module exit function */ +static cmd_export_t cmds[] = {{"as_relay_t", (cmd_function)w_as_relay_t, 1, + fixup_as_relay, 0, REQUEST_ROUTE}, + {"as_relay_sl", (cmd_function)w_as_relay_sl, 1, fixup_as_relay, 0, + REQUEST_ROUTE}, + {0, 0, 0, 0, 0, 0}}; + +static param_export_t params[] = { + {"listen_sockets", PARAM_STRING, &seas_listen_socket}, + {"stats_socket", PARAM_STRING, &seas_stats_socket}, + {"jain_ping", PARAM_STRING, &jain_ping_config}, + {"servlet_ping", PARAM_STRING, &servlet_ping_config}, + {"clusters", PARAM_STRING, &cluster_cfg}, {0, 0, 0}}; + +struct module_exports exports = { + "seas", DEFAULT_DLFLAGS, cmds, /* exported commands */ + params, /* exported parameters */ + 0, /* exported RPC methods */ + 0, /* exported module-items (pseudo variables) */ + 0, /* response function */ + seas_init, /* module initialization function */ + seas_child_init, /* per-child init function */ + seas_exit /* module exit function */ }; -static int fixup_as_relay(void** param, int param_no) +static int fixup_as_relay(void **param, int param_no) { int len; char *parameter; - struct as_entry **entry,*tmp; + struct as_entry **entry, *tmp; - parameter=(char *)(*param); + parameter = (char *)(*param); - if (param_no!=1) + if(param_no != 1) return 0; - len=strlen(parameter); + len = strlen(parameter); - for (entry=&as_list;*entry;entry=&((*entry)->next)) { - if (len== (*entry)->name.len && - !memcmp((*entry)->name.s,parameter,len)) { + for(entry = &as_list; *entry; entry = &((*entry)->next)) { + if(len == (*entry)->name.len + && !memcmp((*entry)->name.s, parameter, len)) { pkg_free(*param); - *param=*entry; + *param = *entry; return 1; } } - if (!(*entry)) { - if (!(*entry=(struct as_entry *)shm_malloc(sizeof(struct as_entry)))) { + if(!(*entry)) { + if(!(*entry = (struct as_entry *)shm_malloc(sizeof(struct as_entry)))) { LM_ERR("no more shm_mem\n"); goto error; } - memset(*entry,0,sizeof(struct as_entry)); - if(!((*entry)->name.s=shm_malloc(len))){ + memset(*entry, 0, sizeof(struct as_entry)); + if(!((*entry)->name.s = shm_malloc(len))) { LM_ERR("no more share mem\n"); goto error; } - (*entry)->name.len=len; - memcpy((*entry)->name.s,parameter,len); - (*entry)->u.as.name=(*entry)->name; - (*entry)->u.as.event_fd=(*entry)->u.as.action_fd=-1; - (*entry)->type=AS_TYPE; + (*entry)->name.len = len; + memcpy((*entry)->name.s, parameter, len); + (*entry)->u.as.name = (*entry)->name; + (*entry)->u.as.event_fd = (*entry)->u.as.action_fd = -1; + (*entry)->type = AS_TYPE; pkg_free(*param); - *param=*entry; + *param = *entry; } - for (tmp=as_list;tmp;tmp=tmp->next) - LM_DBG("%.*s\n",tmp->name.len,tmp->name.s); + for(tmp = as_list; tmp; tmp = tmp->next) + LM_DBG("%.*s\n", tmp->name.len, tmp->name.s); return 1; error: return -1; @@ -170,19 +161,19 @@ void seas_sighandler(int signo) { struct as_entry *as; if(is_dispatcher) - sig_flag=signo; - switch(signo){ + sig_flag = signo; + switch(signo) { case SIGPIPE: if(is_dispatcher) return; - LM_INFO("%s exiting\n",whoami); - if(my_as->u.as.ac_buffer.s){ + LM_INFO("%s exiting\n", whoami); + if(my_as->u.as.ac_buffer.s) { pkg_free(my_as->u.as.ac_buffer.s); - my_as->u.as.ac_buffer.s=0; + my_as->u.as.ac_buffer.s = 0; } - if(my_as->u.as.action_fd!=-1){ + if(my_as->u.as.action_fd != -1) { close(my_as->u.as.action_fd); - my_as->u.as.action_fd=-1; + my_as->u.as.action_fd = -1; } exit(0); break; @@ -198,22 +189,23 @@ void seas_sighandler(int signo) break; case SIGINT: case SIGTERM: - LM_INFO("INFO: signal %d received\n",signo); + LM_INFO("INFO: signal %d received\n", signo); #ifdef PKG_MALLOC pkg_status(); #endif - if(is_dispatcher){ - for (as=as_list;as;as=as->next) { - if(as->type==AS_TYPE && as->connected) - kill(as->u.as.action_pid,signo); + if(is_dispatcher) { + for(as = as_list; as; as = as->next) { + if(as->type == AS_TYPE && as->connected) + kill(as->u.as.action_pid, signo); } - while(wait(0) > 0); + while(wait(0) > 0) + ; exit(0); - }else{ - LM_INFO("%s exiting\n",whoami); + } else { + LM_INFO("%s exiting\n", whoami); if(my_as && my_as->u.as.ac_buffer.s) pkg_free(my_as->u.as.ac_buffer.s); - if(my_as && my_as->u.as.action_fd!=-1) + if(my_as && my_as->u.as.action_fd != -1) close(my_as->u.as.action_fd); exit(0); } @@ -228,15 +220,15 @@ void seas_sighandler(int signo) static int w_as_relay_t(struct sip_msg *msg, char *entry, char *foo) { as_msg_p my_as_ev; - int new_tran,ret=0,len; - char *buffer,processor_id; + int new_tran, ret = 0, len; + char *buffer, processor_id; struct cell *mycel; struct as_entry *as; - char *msg100="Your call is important to us"; - char *msg500="Server Internal Error!"; + char *msg100 = "Your call is important to us"; + char *msg500 = "Server Internal Error!"; - buffer=(char*)0; - my_as_ev=(as_msg_p)0; + buffer = (char *)0; + my_as_ev = (as_msg_p)0; /** * returns <0 on error @@ -244,43 +236,44 @@ static int w_as_relay_t(struct sip_msg *msg, char *entry, char *foo) * 0 if it was a retransmission */ new_tran = seas_f.tmb.t_newtran(msg); - if(new_tran<0) { - ret = (ser_error==E_BAD_VIA && reply_to_via) ? 0 : new_tran; + if(new_tran < 0) { + ret = (ser_error == E_BAD_VIA && reply_to_via) ? 0 : new_tran; goto done; } /*retransmission: script processing should be stopped*/ - if (new_tran==0 && !(msg->REQ_METHOD==METHOD_ACK)){ + if(new_tran == 0 && !(msg->REQ_METHOD == METHOD_ACK)) { ret = 0; goto done; } /*new transaction created, let's pass it to an APP SERVER*/ - if (msg->REQ_METHOD==METHOD_INVITE ) - { + if(msg->REQ_METHOD == METHOD_INVITE) { LM_DBG("new INVITE\n"); - if(!seas_f.tmb.t_reply(msg,100,msg100)){ + if(!seas_f.tmb.t_reply(msg, 100, msg100)) { LM_DBG("t_reply (100)\n"); goto error; } } - as=(struct as_entry *)entry; - if(!as->connected){ - LM_ERR("app server %.*s not connected\n",as->name.len,as->name.s); + as = (struct as_entry *)entry; + if(!as->connected) { + LM_ERR("app server %.*s not connected\n", as->name.len, as->name.s); goto error; } - if(as->type==AS_TYPE){ - if((processor_id=get_processor_id(&msg->rcv,&(as->u.as)))<0){ - LM_ERR("no processor found for packet dst %s:%d\n",ip_addr2a(&msg->rcv.dst_ip),msg->rcv.dst_port); + if(as->type == AS_TYPE) { + if((processor_id = get_processor_id(&msg->rcv, &(as->u.as))) < 0) { + LM_ERR("no processor found for packet dst %s:%d\n", + ip_addr2a(&msg->rcv.dst_ip), msg->rcv.dst_port); goto error; } - }else if(as->type==CLUSTER_TYPE){ + } else if(as->type == CLUSTER_TYPE) { LM_ERR("clustering not fully implemented\n"); return 0; - }else{ + } else { LM_ERR("unknown type of as (neither cluster nor as)\n"); return -1; } - LM_DBG("as found ! (%.*s) processor id = %d\n",as->name.len,as->name.s,processor_id); - if(new_tran==1 && msg->REQ_METHOD==METHOD_ACK){ + LM_DBG("as found ! (%.*s) processor id = %d\n", as->name.len, as->name.s, + processor_id); + if(new_tran == 1 && msg->REQ_METHOD == METHOD_ACK) { LM_DBG("message handled in transaction callbacks. skipping\n"); ret = 0; goto done; @@ -291,11 +284,12 @@ static int w_as_relay_t(struct sip_msg *msg, char *entry, char *foo) * goto error; * } */ - }else if(!(buffer=create_as_event_t(seas_f.tmb.t_gett(),msg,processor_id,&len,0))){ + } else if(!(buffer = create_as_event_t( + seas_f.tmb.t_gett(), msg, processor_id, &len, 0))) { LM_ERR("unable to create event code\n"); goto error; } - if(!(my_as_ev=shm_malloc(sizeof(as_msg_t)))){ + if(!(my_as_ev = shm_malloc(sizeof(as_msg_t)))) { LM_ERR("Out of shared mem!\n"); goto error; } @@ -303,28 +297,29 @@ static int w_as_relay_t(struct sip_msg *msg, char *entry, char *foo) my_as_ev->as = as; my_as_ev->type = T_REQ_IN; my_as_ev->len = len; - my_as_ev->transaction=seas_f.tmb.t_gett(); /*does not refcount*/ - if(use_stats && new_tran>0) + my_as_ev->transaction = seas_f.tmb.t_gett(); /*does not refcount*/ + if(use_stats && new_tran > 0) as_relay_stat(seas_f.tmb.t_gett()); again: - ret=write(write_pipe,&my_as_ev,sizeof(as_msg_p)); - if(ret==-1){ - if(errno==EINTR) + ret = write(write_pipe, &my_as_ev, sizeof(as_msg_p)); + if(ret == -1) { + if(errno == EINTR) goto again; - else if(errno==EPIPE){ - LM_ERR("SEAS Event Dispatcher has closed the pipe. Invalidating it !\n"); + else if(errno == EPIPE) { + LM_ERR("SEAS Event Dispatcher has closed the pipe. Invalidating it " + "!\n"); goto error; /** TODO handle this correctly !!!*/ } } /* seas_f.tmb.t_setkr(REQ_FWDED); */ - ret=0; + ret = 0; done: return ret; error: - mycel=seas_f.tmb.t_gett(); - if(mycel && mycel!=T_UNDEFINED){ - if(!seas_f.tmb.t_reply(msg,500,msg500)){ + mycel = seas_f.tmb.t_gett(); + if(mycel && mycel != T_UNDEFINED) { + if(!seas_f.tmb.t_reply(msg, 500, msg500)) { LM_ERR("t_reply (500)\n"); } } @@ -342,47 +337,50 @@ static int w_as_relay_t(struct sip_msg *msg, char *entry, char *foo) */ static int w_as_relay_sl(struct sip_msg *msg, char *as_name, char *foo) { - as_msg_p my_as_ev=0; - int ret=0,len; - char *buffer=0,processor_id; + as_msg_p my_as_ev = 0; + int ret = 0, len; + char *buffer = 0, processor_id; struct as_entry *as; - as=(struct as_entry *)as_name; + as = (struct as_entry *)as_name; - if(as->type==AS_TYPE){ - if((processor_id=get_processor_id(&msg->rcv,&(as->u.as)))<0){ - LM_ERR("no processor found for packet with dst port:%d\n",msg->rcv.dst_port); + if(as->type == AS_TYPE) { + if((processor_id = get_processor_id(&msg->rcv, &(as->u.as))) < 0) { + LM_ERR("no processor found for packet with dst port:%d\n", + msg->rcv.dst_port); goto error; } - }else if (as->type==CLUSTER_TYPE) { + } else if(as->type == CLUSTER_TYPE) { LM_ERR("clustering not fully implemented\n"); goto error; - }else{ + } else { LM_ERR("unknown type of as\n"); goto error; } - LM_DBG("as found ! (%.*s) processor id = %d\n",as->name.len,as->name.s,processor_id); - if(!(buffer=create_as_event_sl(msg,processor_id,&len,0))){ + LM_DBG("as found ! (%.*s) processor id = %d\n", as->name.len, as->name.s, + processor_id); + if(!(buffer = create_as_event_sl(msg, processor_id, &len, 0))) { LM_ERR("unable to create event code\n"); goto error; } - if(!(my_as_ev=shm_malloc(sizeof(as_msg_t)))) + if(!(my_as_ev = shm_malloc(sizeof(as_msg_t)))) goto error; my_as_ev->msg = buffer; my_as_ev->as = as; my_as_ev->type = SL_REQ_IN; my_as_ev->len = len; - my_as_ev->transaction=seas_f.tmb.t_gett(); /*does not refcount*/ + my_as_ev->transaction = seas_f.tmb.t_gett(); /*does not refcount*/ if(use_stats) as_relay_stat(seas_f.tmb.t_gett()); again: - ret=write(write_pipe,&my_as_ev,sizeof(as_msg_p)); - if(ret==-1){ - if(errno==EINTR) + ret = write(write_pipe, &my_as_ev, sizeof(as_msg_p)); + if(ret == -1) { + if(errno == EINTR) goto again; - else if(errno==EPIPE){ - LM_ERR("SEAS Event Dispatcher has closed the pipe. Invalidating it !\n"); + else if(errno == EPIPE) { + LM_ERR("SEAS Event Dispatcher has closed the pipe. Invalidating it " + "!\n"); return -2; /** TODO handle this correctly !!!*/ } @@ -394,7 +392,7 @@ static int w_as_relay_sl(struct sip_msg *msg, char *as_name, char *foo) //t_release(msg, 0, 0); /* seas_f.tmb.t_setkr(REQ_FWDED); */ - ret=0; + ret = 0; return ret; error: if(my_as_ev) @@ -421,104 +419,106 @@ static int w_as_relay_sl(struct sip_msg *msg, char *as_name, char *foo) * [cancelled hash_index,label] * */ -char * create_as_event_t(struct cell *t,struct sip_msg *msg,char processor_id,int *evt_len,int flags) +char *create_as_event_t(struct cell *t, struct sip_msg *msg, char processor_id, + int *evt_len, int flags) { - unsigned int i,hash_index,label; + unsigned int i, hash_index, label; unsigned short int port; - unsigned int k,len; - char *buffer=NULL; + unsigned int k, len; + char *buffer = NULL; struct cell *originalT; - originalT=0; + originalT = 0; - if(!(buffer=shm_malloc(ENCODED_MSG_SIZE))){ + if(!(buffer = shm_malloc(ENCODED_MSG_SIZE))) { LM_ERR("Out Of Memory !!\n"); return 0; } - *evt_len=0; - if(t){ - hash_index=t->hash_index; - label=t->label; - }else{ + *evt_len = 0; + if(t) { + hash_index = t->hash_index; + label = t->label; + } else { /**seas_f.tmb.t_get_trans_ident(msg,&hash_index,&label); this is bad, because it ref-counts !!!*/ LM_ERR("no transaction provided...\n"); goto error; } - k=4; + k = 4; /*type*/ - buffer[k++]=(unsigned char)T_REQ_IN; + buffer[k++] = (unsigned char)T_REQ_IN; /*processor_id*/ - buffer[k++]=(unsigned char)processor_id; + buffer[k++] = (unsigned char)processor_id; /*flags*/ - if(is_e2e_ack(t,msg)){ - flags|=E2E_ACK; - }else if(msg->REQ_METHOD==METHOD_CANCEL){ + if(is_e2e_ack(t, msg)) { + flags |= E2E_ACK; + } else if(msg->REQ_METHOD == METHOD_CANCEL) { LM_DBG("new CANCEL\n"); - originalT=seas_f.tmb.t_lookup_original(msg); - if(!originalT || originalT==T_UNDEFINED){ + originalT = seas_f.tmb.t_lookup_original(msg); + if(!originalT || originalT == T_UNDEFINED) { /** we don't even pass the unknown CANCEL to JAIN*/ LM_WARN("CANCEL does not match any existing transaction!!\n"); goto error; - }else{ - flags|=CANCEL_FOUND; + } else { + flags |= CANCEL_FOUND; //seas_f.tmb.unref_cell(originalT); } LM_DBG("Cancelling transaction !!\n"); } - flags=htonl(flags); - memcpy(buffer+k,&flags,4); - k+=4; + flags = htonl(flags); + memcpy(buffer + k, &flags, 4); + k += 4; /*protocol should be UDP,TCP,TLS or whatever*/ - buffer[k++]=(unsigned char)msg->rcv.proto; + buffer[k++] = (unsigned char)msg->rcv.proto; /*src ip len + src ip*/ - len=msg->rcv.src_ip.len; - buffer[k++]=(unsigned char)len; - memcpy(buffer+k,&(msg->rcv.src_ip.u),len); - k+=len; + len = msg->rcv.src_ip.len; + buffer[k++] = (unsigned char)len; + memcpy(buffer + k, &(msg->rcv.src_ip.u), len); + k += len; /*dst ip len + dst ip*/ - len=msg->rcv.dst_ip.len; - buffer[k++]=(unsigned char)len; - memcpy(buffer+k,&(msg->rcv.dst_ip.u),len); - k+=len; + len = msg->rcv.dst_ip.len; + buffer[k++] = (unsigned char)len; + memcpy(buffer + k, &(msg->rcv.dst_ip.u), len); + k += len; /*src port */ - port=htons(msg->rcv.src_port); - memcpy(buffer+k,&port,2); - k+=2; + port = htons(msg->rcv.src_port); + memcpy(buffer + k, &port, 2); + k += 2; /*dst port */ - port=htons(msg->rcv.dst_port); - memcpy(buffer+k,&port,2); - k+=2; + port = htons(msg->rcv.dst_port); + memcpy(buffer + k, &port, 2); + k += 2; /*hash_index*/ - i=htonl(hash_index); - memcpy(buffer+k,&i,4); - k+=4; + i = htonl(hash_index); + memcpy(buffer + k, &i, 4); + k += 4; /*label (is the collision slot in the hash-table)*/ - i=htonl(label); - memcpy(buffer+k,&i,4); - k+=4; - if(msg->REQ_METHOD==METHOD_CANCEL && originalT){ - LM_DBG("Cancelled transaction: Hash_Index=%d, Label=%d\n",originalT->hash_index,originalT->label); + i = htonl(label); + memcpy(buffer + k, &i, 4); + k += 4; + if(msg->REQ_METHOD == METHOD_CANCEL && originalT) { + LM_DBG("Cancelled transaction: Hash_Index=%d, Label=%d\n", + originalT->hash_index, originalT->label); /*hash_index*/ - i=htonl(originalT->hash_index); - memcpy(buffer+k,&i,4); - k+=4; + i = htonl(originalT->hash_index); + memcpy(buffer + k, &i, 4); + k += 4; /*label (is the collision slot in the hash-table)*/ - i=htonl(originalT->label); - memcpy(buffer+k,&i,4); - k+=4; + i = htonl(originalT->label); + memcpy(buffer + k, &i, 4); + k += 4; } /*length of event (hdr+payload-4), copied at the beginning*/ - if(encode_msg(msg,buffer+k,ENCODED_MSG_SIZE-k)<0){ + if(encode_msg(msg, buffer + k, ENCODED_MSG_SIZE - k) < 0) { LM_ERR("Unable to encode msg\n"); goto error; } - i = GET_PAY_SIZE(buffer+k); - k+=i; - *evt_len=k; - k=htonl(k); - memcpy(buffer,&k,4); + i = GET_PAY_SIZE(buffer + k); + k += i; + *evt_len = k; + k = htonl(k); + memcpy(buffer, &k, 4); return buffer; error: if(buffer) @@ -542,59 +542,60 @@ char * create_as_event_t(struct cell *t,struct sip_msg *msg,char processor_id,in * dst_port(2), * */ -char * create_as_event_sl(struct sip_msg *msg,char processor_id,int *evt_len,int flags) +char *create_as_event_sl( + struct sip_msg *msg, char processor_id, int *evt_len, int flags) { unsigned int i; unsigned short int port; - unsigned int k,len; - char *buffer=NULL; + unsigned int k, len; + char *buffer = NULL; - if(!(buffer=shm_malloc(ENCODED_MSG_SIZE))){ + if(!(buffer = shm_malloc(ENCODED_MSG_SIZE))) { LM_ERR("create_as_event_t Out Of Memory !!\n"); return 0; } - *evt_len=0; + *evt_len = 0; /*leave 4 bytes for event length*/ - k=4; + k = 4; /*type*/ - buffer[k++]=(unsigned char)SL_REQ_IN; + buffer[k++] = (unsigned char)SL_REQ_IN; /*processor_id*/ - buffer[k++]=(unsigned char)processor_id; + buffer[k++] = (unsigned char)processor_id; /*flags*/ - flags=htonl(flags); - memcpy(buffer+k,&flags,4); - k+=4; + flags = htonl(flags); + memcpy(buffer + k, &flags, 4); + k += 4; /*protocol should be UDP,TCP,TLS or whatever*/ - buffer[k++]=(unsigned char)msg->rcv.proto; + buffer[k++] = (unsigned char)msg->rcv.proto; /*src ip len + src ip*/ - len=msg->rcv.src_ip.len; - buffer[k++]=(unsigned char)len; - memcpy(buffer+k,&(msg->rcv.src_ip.u),len); - k+=len; + len = msg->rcv.src_ip.len; + buffer[k++] = (unsigned char)len; + memcpy(buffer + k, &(msg->rcv.src_ip.u), len); + k += len; /*dst ip len + dst ip*/ - len=msg->rcv.dst_ip.len; - buffer[k++]=(unsigned char)len; - memcpy(buffer+k,&(msg->rcv.dst_ip.u),len); - k+=len; + len = msg->rcv.dst_ip.len; + buffer[k++] = (unsigned char)len; + memcpy(buffer + k, &(msg->rcv.dst_ip.u), len); + k += len; /*src port */ - port=htons(msg->rcv.src_port); - memcpy(buffer+k,&port,2); - k+=2; + port = htons(msg->rcv.src_port); + memcpy(buffer + k, &port, 2); + k += 2; /*dst port */ - port=htons(msg->rcv.dst_port); - memcpy(buffer+k,&port,2); - k+=2; + port = htons(msg->rcv.dst_port); + memcpy(buffer + k, &port, 2); + k += 2; /*length of event (hdr+payload-4), copied at the beginning*/ - if(encode_msg(msg,buffer+k,ENCODED_MSG_SIZE-k)<0){ + if(encode_msg(msg, buffer + k, ENCODED_MSG_SIZE - k) < 0) { LM_ERR("Unable to encode msg\n"); goto error; } - i = GET_PAY_SIZE(buffer+k); - k+=i; - *evt_len=k; - k=htonl(k); - memcpy(buffer,&k,4); + i = GET_PAY_SIZE(buffer + k); + k += i; + *evt_len = k; + k = htonl(k); + memcpy(buffer, &k, 4); return buffer; error: if(buffer) @@ -603,11 +604,11 @@ char * create_as_event_sl(struct sip_msg *msg,char processor_id,int *evt_len,int } -static inline int is_e2e_ack(struct cell *t,struct sip_msg *msg) +static inline int is_e2e_ack(struct cell *t, struct sip_msg *msg) { if(msg->REQ_METHOD != METHOD_ACK) return 0; - if (t->uas.status<300) + if(t->uas.status < 300) return 1; return 0; } @@ -618,60 +619,65 @@ static inline int is_e2e_ack(struct cell *t,struct sip_msg *msg) */ static int seas_init(void) { - char *p,*port; + char *p, *port; struct hostent *he; struct socket_info *si; - int c_pipe[2],mierr,i; + int c_pipe[2], mierr, i; /** Populate seas_functions*/ - if (load_tm_api(&seas_f.tmb)!=0) { - LM_ERR( "can't load TM API\n"); + if(load_tm_api(&seas_f.tmb) != 0) { + LM_ERR("can't load TM API\n"); return -1; } - if(!(seas_f.t_check_orig_trans = find_export("t_check_trans", 0, 0))){ - LM_ERR( "Seas requires transaction module (t_check_trans not found)\n"); + if(!(seas_f.t_check_orig_trans = find_export("t_check_trans", 0, 0))) { + LM_ERR("Seas requires transaction module (t_check_trans not found)\n"); return -1; } /** Populate seas_functions*/ - c_pipe[0]=c_pipe[1]=-1; - p=seas_listen_socket; - port=(char *)0; - seas_listen_port=5080; + c_pipe[0] = c_pipe[1] = -1; + p = seas_listen_socket; + port = (char *)0; + seas_listen_port = 5080; /*if the seas_listen_socket configuration string is empty, use default values*/ - if(p==NULL || *p==0){ - si=get_first_socket(); - seas_listen_ip=&si->address; - } else {/*if config string is not empty, then try to find host first, and maybe port..*/ - while(*p){ - if(*p == ':'){ - *p=0; - port=p+1; + if(p == NULL || *p == 0) { + si = get_first_socket(); + seas_listen_ip = &si->address; + } else { /*if config string is not empty, then try to find host first, and maybe port..*/ + while(*p) { + if(*p == ':') { + *p = 0; + port = p + 1; break; } p++; } - if(!(he=resolvehost(seas_listen_socket))) + if(!(he = resolvehost(seas_listen_socket))) goto error; - if(!(seas_listen_ip=pkg_malloc(sizeof(struct ip_addr)))) + if(!(seas_listen_ip = pkg_malloc(sizeof(struct ip_addr)))) goto error; hostent2ip_addr(seas_listen_ip, he, 0); - if(port!=(char *)0 && (seas_listen_port=str2s(port,strlen(port),&mierr))==0){ - LM_ERR("invalid port %s \n",port); + if(port != (char *)0 + && (seas_listen_port = str2s(port, strlen(port), &mierr)) + == 0) { + LM_ERR("invalid port %s \n", port); goto error; } } - memset(unc_as_t,0,2*MAX_UNC_AS_NR*sizeof(struct unc_as));//useless because unc_as_t is in bss? - if (pipe(c_pipe)==-1) { + memset(unc_as_t, 0, + 2 * MAX_UNC_AS_NR + * sizeof(struct + unc_as)); //useless because unc_as_t is in bss? + if(pipe(c_pipe) == -1) { LM_ERR("cannot create pipe!\n"); goto error; } - read_pipe=c_pipe[0]; - write_pipe=c_pipe[1]; + read_pipe = c_pipe[0]; + write_pipe = c_pipe[1]; seas_init_tags(); - if(0>start_stats_server(seas_stats_socket)) + if(0 > start_stats_server(seas_stats_socket)) goto error; - if(0>prepare_ha()) + if(0 > prepare_ha()) goto error; - if(0>parse_cluster_cfg()) + if(0 > parse_cluster_cfg()) goto error; register_procs(1); /* add child to update local config framework structures */ @@ -679,10 +685,10 @@ static int seas_init(void) return 0; error: - for(i=0;i<2;i++) - if(c_pipe[i]!=-1) + for(i = 0; i < 2; i++) + if(c_pipe[i] != -1) close(c_pipe[i]); - if(seas_listen_ip!=0) + if(seas_listen_ip != 0) pkg_free(seas_listen_ip); if(use_stats) stop_stats_server(); @@ -694,8 +700,8 @@ static int seas_init(void) */ static void seas_init_tags(void) { - init_tags(seas_tags, &seas_tag_suffix,"VozTele-Seas/tags",'-'); - LM_DBG("seas_init_tags, seas_tags=%s\n",seas_tags); + init_tags(seas_tags, &seas_tag_suffix, "VozTele-Seas/tags", '-'); + LM_DBG("seas_init_tags, seas_tags=%s\n", seas_tags); } /** @@ -711,21 +717,21 @@ static int seas_child_init(int rank) int pid; /* only the child 1 will execute this */ - if (rank != PROC_MAIN){ + if(rank != PROC_MAIN) { /* only dispatcher needs to read from the pipe, so close reading fd*/ /*close(read_pipe);*/ return 0; } - if ((pid=fork_process(PROC_NOCHLDINIT,"SEAS",0))<0) { + if((pid = fork_process(PROC_NOCHLDINIT, "SEAS", 0)) < 0) { LM_ERR("forking failed\n"); return -1; } - if (!pid) { + if(!pid) { /*dispatcher child. we leave writing end open so that new childs spawned * by event dispatcher can also write to pipe.. */ /* initialize the config framework */ - if (cfg_child_init()) + if(cfg_child_init()) return -1; /* close(write_pipe); */ @@ -740,7 +746,8 @@ static int seas_child_init(int rank) */ static void seas_exit(void) { - if( seas_listen_ip!=NULL && seas_listen_ip!=&(get_first_socket()->address)) + if(seas_listen_ip != NULL + && seas_listen_ip != &(get_first_socket()->address)) pkg_free(seas_listen_ip); return; } @@ -750,10 +757,10 @@ static void seas_exit(void) * to the receive_info structure passed. If there is one, it returns its * identifier (number between 0 and 128), otherwise it returns -1; */ -char get_processor_id(struct receive_info *rcv,as_p as) +char get_processor_id(struct receive_info *rcv, as_p as) { int i; - for(i=0;ibound_processor[i]!=0 && (rcv->dst_ip.len == as->binds[i]->address.len) && (rcv->dst_ip.af==as->binds[i]->address.af) && diff --git a/src/modules/seas/seas.h b/src/modules/seas/seas.h index 3244cc96922..e3f85b19258 100644 --- a/src/modules/seas/seas.h +++ b/src/modules/seas/seas.h @@ -22,10 +22,10 @@ #define _SEAS_H #include -#include "../../core/str.h"/*str*/ -#include "../../core/ip_addr.h"/*ip_addr*/ -#include "../../core/sr_module.h" /*version,etc*/ -#include "../../modules/tm/tm_load.h"/*tm_binds*/ +#include "../../core/str.h" /*str*/ +#include "../../core/ip_addr.h" /*ip_addr*/ +#include "../../core/sr_module.h" /*version,etc*/ +#include "../../modules/tm/tm_load.h" /*tm_binds*/ #include "ha.h" #include "cluster.h" #define MAX_AS_NR 5 @@ -65,12 +65,12 @@ #define SPIRAL_FLAG 0x00000001 -#define net2hostL(dst,from,index) do{ \ - memcpy(&(dst),(from)+(index),4); \ - dst=ntohl(dst); \ - (index)+=4; \ -}while(0); - +#define net2hostL(dst, from, index) \ + do { \ + memcpy(&(dst), (from) + (index), 4); \ + dst = ntohl(dst); \ + (index) += 4; \ + } while(0); extern char use_stats; @@ -92,13 +92,15 @@ extern int servlet_pings_lost; extern struct as_entry *as_table; -struct seas_functions{ +struct seas_functions +{ struct tm_binds tmb; cmd_function t_check_orig_trans; }; /*TODO listen_points should be dynamically allocated ?*/ -typedef struct app_server { +typedef struct app_server +{ int event_fd; int action_fd; str name; @@ -111,9 +113,10 @@ typedef struct app_server { struct ha jain_pings; struct ha servlet_pings; struct cluster *cluster; -}as_t, *as_p; +} as_t, *as_p; -struct cluster{ +struct cluster +{ str name; int num; int registered; @@ -129,14 +132,16 @@ struct cluster{ * atomic operation. This way, we prevent having to put a mutex on the array, which would make * it slower , as only one process could be accessing it at a time. */ -struct as_entry{ +struct as_entry +{ str name; int type; int connected; - union{ + union + { struct app_server as; struct cluster cs; - }u; + } u; struct as_entry *next; }; @@ -145,18 +150,21 @@ extern struct as_entry *my_as; extern struct seas_functions seas_f; extern struct as_entry *as_list; -typedef struct as_msg { +typedef struct as_msg +{ struct cell *transaction; char *msg; int len; int type; int id; struct as_entry *as; -}as_msg_t,*as_msg_p; +} as_msg_t, *as_msg_p; -char get_processor_id(struct receive_info *rcv,as_p as); +char get_processor_id(struct receive_info *rcv, as_p as); void seas_sighandler(int signo); -char* create_as_event_t(struct cell *t,struct sip_msg *msg,char processor_id,int *evt_len,int flags); -char* create_as_event_sl(struct sip_msg *msg,char processor_id,int *evt_len,int flags); +char *create_as_event_t(struct cell *t, struct sip_msg *msg, char processor_id, + int *evt_len, int flags); +char *create_as_event_sl( + struct sip_msg *msg, char processor_id, int *evt_len, int flags); #endif diff --git a/src/modules/seas/seas_action.c b/src/modules/seas/seas_action.c index e91c740a319..6764ebf198b 100644 --- a/src/modules/seas/seas_action.c +++ b/src/modules/seas/seas_action.c @@ -30,22 +30,22 @@ #include "../../core/mem/mem.h" #include "../../core/dprint.h" #include "../../core/str.h" -#include "../../core/pt.h"/*process_count*/ +#include "../../core/pt.h" /*process_count*/ #include "../../core/ip_addr.h" #include "../../core/tags.h" #include "../../core/error.h" #include "../../core/ut.h" #include "../../core/parser/hf.h" #include "../../core/parser/parse_fline.h" -#include "../../core/parser/parser_f.h"/*find_not_quoted*/ +#include "../../core/parser/parser_f.h" /*find_not_quoted*/ #include "../../core/parser/parse_to.h" #include "../../core/parser/parse_from.h" #include "../../core/parser/parse_cseq.h" #include "../../core/parser/parse_content.h" -#include "../../core/parser/parse_rr.h"/*parse_rr*/ -#include "../../core/parser/parse_via.h"/*parse_via*/ -#include "../../core/parser/parse_param.h"/*parse_params*/ -#include "../../core/parser/parse_uri.h" /*parse_uri*/ +#include "../../core/parser/parse_rr.h" /*parse_rr*/ +#include "../../core/parser/parse_via.h" /*parse_via*/ +#include "../../core/parser/parse_param.h" /*parse_params*/ +#include "../../core/parser/parse_uri.h" /*parse_uri*/ #include "../../core/parser/msg_parser.h" #include "encode_msg.h" #include "../../modules/tm/t_lookup.h" @@ -60,135 +60,145 @@ #define MAX_HEADER 1024 #define SPIRAL_HDR "X-WeSIP-SPIRAL: true" -#define SPIRAL_HDR_LEN (sizeof(SPIRAL_HDR)-1) +#define SPIRAL_HDR_LEN (sizeof(SPIRAL_HDR) - 1) #define RECORD_ROUTE "Record-Route: " -#define RECORD_ROUTE_LEN (sizeof(RECORD_ROUTE)-1) +#define RECORD_ROUTE_LEN (sizeof(RECORD_ROUTE) - 1) #define VIA "Via: " -#define VIA_LEN (sizeof(VIA)-1) +#define VIA_LEN (sizeof(VIA) - 1) extern char *seas_tag_suffix; extern char seas_tags[]; pid_t my_parent; extern int fifo_pid; -static inline struct sip_msg *parse_ac_msg(hdr_flags_t flags,char *start,int len); +static inline struct sip_msg *parse_ac_msg( + hdr_flags_t flags, char *start, int len); static inline void free_sip_msg_lite(struct sip_msg *my_msg); -static inline int calculate_hooks(dlg_t* _d); +static inline int calculate_hooks(dlg_t *_d); static inline int process_input(int fd); static inline int process_pings(struct ha *the_table); -static inline int ac_jain_pong(as_p the_as,unsigned char processor_id,unsigned int flags,char *action,int len); -int process_pong(struct ha *the_table,unsigned int seqno); -int print_local_uri(as_p as,char processor_id,char *where,int len); -void uas_e2e_ack_cb(struct cell* t, int type,struct tmcb_params *rcvd_params); +static inline int ac_jain_pong(as_p the_as, unsigned char processor_id, + unsigned int flags, char *action, int len); +int process_pong(struct ha *the_table, unsigned int seqno); +int print_local_uri(as_p as, char processor_id, char *where, int len); +void uas_e2e_ack_cb(struct cell *t, int type, struct tmcb_params *rcvd_params); int dispatch_actions(void) { - int fd,n,ret,timeout,elapsed_ms; - static int ktimeout; - struct pollfd fds[1]; - struct timeval last,now; + int fd, n, ret, timeout, elapsed_ms; + static int ktimeout; + struct pollfd fds[1]; + struct timeval last, now; - /* now the process_no is set, I delete the pt (process_table) global var, + /* now the process_no is set, I delete the pt (process_table) global var, * because it confuses LM_*() */ - pt=0; - fd=my_as->u.as.action_fd; - fds[0].fd=fd; - fds[0].events=POLLIN|POLLHUP; - fds[0].revents=0; - my_parent=getppid(); - snprintf(whoami,MAX_WHOAMI_LEN,"[%.*s] Action dispatcher",my_as->name.len,my_as->name.s); - if(jain_ping_timeout && servlet_ping_timeout) - ktimeout=jain_ping_timeoutu.as.ac_buffer.s = pkg_malloc(AS_BUF_SIZE))==0){ - LM_ERR("no more pkg mem\n"); - return -1; - } - my_as->u.as.ac_buffer.len=0; - if(use_ha){ - timeout=ktimeout; - while(1){ - gettimeofday(&last,NULL); - print_pingtable(&my_as->u.as.jain_pings,-1,1); - if(0>(n=poll(fds,1,timeout))){ - if(errno==EINTR){ - gettimeofday(&last,NULL); - continue; - }else if(errno==EBADF){ - LM_ERR("EBADF !!\n"); - }else{ - LM_ERR("on poll\n"); - } - }else if(n==0){/*timeout*/ - if (0>(ret=process_pings(&my_as->u.as.jain_pings))) { - return ret; - } - timeout=ktimeout; - }else{ /*events*/ - if (0>(ret=process_input(fd))) { - return ret; - } - gettimeofday(&now,NULL); - elapsed_ms=((now.tv_sec-last.tv_sec)*1000)+((now.tv_usec-last.tv_usec)/1000); - if(elapsed_ms(ret=process_pings(&my_as->u.as.jain_pings))){ - return ret; - } - timeout=ktimeout; - } - } - fds[0].events=POLLIN|POLLHUP; - fds[0].revents=0; - } - }else{ - do{ - ret=process_input(fd); - }while(ret>=0); - } + pt = 0; + fd = my_as->u.as.action_fd; + fds[0].fd = fd; + fds[0].events = POLLIN | POLLHUP; + fds[0].revents = 0; + my_parent = getppid(); + snprintf(whoami, MAX_WHOAMI_LEN, "[%.*s] Action dispatcher", + my_as->name.len, my_as->name.s); + if(jain_ping_timeout && servlet_ping_timeout) + ktimeout = jain_ping_timeout < servlet_ping_timeout + ? jain_ping_timeout + : servlet_ping_timeout; + else if(jain_ping_timeout) + ktimeout = jain_ping_timeout; + else if(servlet_ping_timeout) + ktimeout = servlet_ping_timeout; + /*ac_buffer is pkg_malloc because only this process (action dispatcher) will use it*/ + if((my_as->u.as.ac_buffer.s = pkg_malloc(AS_BUF_SIZE)) == 0) { + LM_ERR("no more pkg mem\n"); + return -1; + } + my_as->u.as.ac_buffer.len = 0; + if(use_ha) { + timeout = ktimeout; + while(1) { + gettimeofday(&last, NULL); + print_pingtable(&my_as->u.as.jain_pings, -1, 1); + if(0 > (n = poll(fds, 1, timeout))) { + if(errno == EINTR) { + gettimeofday(&last, NULL); + continue; + } else if(errno == EBADF) { + LM_ERR("EBADF !!\n"); + } else { + LM_ERR("on poll\n"); + } + } else if(n == 0) { /*timeout*/ + if(0 > (ret = process_pings(&my_as->u.as.jain_pings))) { + return ret; + } + timeout = ktimeout; + } else { /*events*/ + if(0 > (ret = process_input(fd))) { + return ret; + } + gettimeofday(&now, NULL); + elapsed_ms = ((now.tv_sec - last.tv_sec) * 1000) + + ((now.tv_usec - last.tv_usec) / 1000); + if(elapsed_ms < timeout) { + timeout -= elapsed_ms; + } else { + if(0 > (ret = process_pings(&my_as->u.as.jain_pings))) { + return ret; + } + timeout = ktimeout; + } + } + fds[0].events = POLLIN | POLLHUP; + fds[0].revents = 0; + } + } else { + do { + ret = process_input(fd); + } while(ret >= 0); + } - return 0; + return 0; } static inline int process_input(int fd) { - int j,k; + int j, k; - k=AS_BUF_SIZE-(my_as->u.as.ac_buffer.len); + k = AS_BUF_SIZE - (my_as->u.as.ac_buffer.len); again: - if(0>(j=read(fd,my_as->u.as.ac_buffer.s+my_as->u.as.ac_buffer.len,k))){ - if(errno==EINTR) - goto again; - LM_ERR("reading data for as %.*s (%s)\n",my_as->name.len,my_as->name.s,strerror(errno)); - return -1; - }else if(j==0){ - pkg_free(my_as->u.as.ac_buffer.s); - close(fd); - LM_ERR("read 0 bytes from AS:%.*s\n",my_as->name.len,my_as->name.s); - /** we return, so we will exit, so our parent (Event Dispatcher) will receive a sigchld and know + if(0 > (j = read(fd, my_as->u.as.ac_buffer.s + my_as->u.as.ac_buffer.len, + k))) { + if(errno == EINTR) + goto again; + LM_ERR("reading data for as %.*s (%s)\n", my_as->name.len, + my_as->name.s, strerror(errno)); + return -1; + } else if(j == 0) { + pkg_free(my_as->u.as.ac_buffer.s); + close(fd); + LM_ERR("read 0 bytes from AS:%.*s\n", my_as->name.len, my_as->name.s); + /** we return, so we will exit, so our parent (Event Dispatcher) will receive a sigchld and know * it should tear down the corresponding AS * what still is not clear is what will happen to events that were put in the pipe... */ - return -2; - } - (my_as->u.as.ac_buffer.len)+=j; - LM_DBG("read %d bytes from AS action socket (total = %d)\n",j,my_as->u.as.ac_buffer.len); - if(use_stats) - receivedplus(); - if(my_as->u.as.ac_buffer.len>=10){ - process_action(&my_as->u.as); - LM_DBG("(Action dispatched,buffer.len=%d)\n",my_as->u.as.ac_buffer.len); - } - return 0; + return -2; + } + (my_as->u.as.ac_buffer.len) += j; + LM_DBG("read %d bytes from AS action socket (total = %d)\n", j, + my_as->u.as.ac_buffer.len); + if(use_stats) + receivedplus(); + if(my_as->u.as.ac_buffer.len >= 10) { + process_action(&my_as->u.as); + LM_DBG("(Action dispatched,buffer.len=%d)\n", + my_as->u.as.ac_buffer.len); + } + return 0; } /** @@ -207,33 +217,34 @@ static inline int process_input(int fd) */ static inline int process_pings(struct ha *the_table) { - int i,k,elapsed; - struct ping *tmp; - struct timeval now; - - tmp=NULL; - gettimeofday(&now,NULL); - if(the_table->count==0) - return 0; - lock_get(the_table->mutex); - { - print_pingtable(the_table,-1,0); - for(i=0;icount;i++){ - k=(the_table->begin+i)%the_table->size; - tmp=the_table->pings+k; - elapsed=(now.tv_sec-tmp->sent.tv_sec)*1000+(now.tv_usec-tmp->sent.tv_usec)/1000; - if(elapsed>the_table->timeout){ - LM_DBG("ping timed out %d\n",tmp->id); - the_table->timed_out_pings++; - }else{ - the_table->begin=k; - the_table->count-=i; - break; - } - } - } - lock_release(the_table->mutex); - return 0; + int i, k, elapsed; + struct ping *tmp; + struct timeval now; + + tmp = NULL; + gettimeofday(&now, NULL); + if(the_table->count == 0) + return 0; + lock_get(the_table->mutex); + { + print_pingtable(the_table, -1, 0); + for(i = 0; i < the_table->count; i++) { + k = (the_table->begin + i) % the_table->size; + tmp = the_table->pings + k; + elapsed = (now.tv_sec - tmp->sent.tv_sec) * 1000 + + (now.tv_usec - tmp->sent.tv_usec) / 1000; + if(elapsed > the_table->timeout) { + LM_DBG("ping timed out %d\n", tmp->id); + the_table->timed_out_pings++; + } else { + the_table->begin = k; + the_table->count -= i; + break; + } + } + } + lock_release(the_table->mutex); + return 0; } /* Because TransactionModule organizes statistics based on process_no, @@ -270,112 +281,135 @@ static inline void set_process_no() */ int process_action(as_p the_as) { - unsigned int ac_len; - unsigned char processor_id,type; - unsigned int flags; - - ac_len=(the_as->ac_buffer.s[0]<<24)|(the_as->ac_buffer.s[1]<<16)|(the_as->ac_buffer.s[2]<<8)|((the_as->ac_buffer.s[3])&0xFF); - type=the_as->ac_buffer.s[4]; - processor_id=the_as->ac_buffer.s[5]; - flags=(the_as->ac_buffer.s[6]<<24)|(the_as->ac_buffer.s[7]<<16)|(the_as->ac_buffer.s[8]<<8)|((the_as->ac_buffer.s[9])&0xFF); - /*yeah, it comes in network byte order*/ - /*if ac_len > BUF_SIZE then a flag should be put on the AS so that the whole length + unsigned int ac_len; + unsigned char processor_id, type; + unsigned int flags; + + ac_len = (the_as->ac_buffer.s[0] << 24) | (the_as->ac_buffer.s[1] << 16) + | (the_as->ac_buffer.s[2] << 8) + | ((the_as->ac_buffer.s[3]) & 0xFF); + type = the_as->ac_buffer.s[4]; + processor_id = the_as->ac_buffer.s[5]; + flags = (the_as->ac_buffer.s[6] << 24) | (the_as->ac_buffer.s[7] << 16) + | (the_as->ac_buffer.s[8] << 8) | ((the_as->ac_buffer.s[9]) & 0xFF); + /*yeah, it comes in network byte order*/ + /*if ac_len > BUF_SIZE then a flag should be put on the AS so that the whole length * of the action is skipped, until a mechanism for handling big packets is implemented*/ - if(use_stats) - stats_reply(); - if(ac_len>AS_BUF_SIZE){ - LM_WARN("action too big (%d)!!! should be skipped and" - " an error returned!\n",ac_len); - return -1; - } - while (the_as->ac_buffer.len>=ac_len) { - LM_DBG("Processing action %d bytes long\n",ac_len); - switch(type){ - case REPLY_PROV: - case REPLY_FIN: - LM_DBG("Processing a REPLY action from AS (length=%d): %.*s\n", - ac_len,the_as->name.len,the_as->name.s); - ac_reply(the_as,processor_id,flags,the_as->ac_buffer.s+10,ac_len-10); - break; - case UAC_REQ: - LM_DBG("Processing an UAC REQUEST action from AS (length=%d): %.*s\n", - ac_len,the_as->name.len,the_as->name.s); - ac_uac_req(the_as,processor_id,flags,the_as->ac_buffer.s+10,ac_len-10); - break; - case AC_CANCEL: - LM_DBG("Processing a CANCEL REQUEST action from AS (length=%d): %.*s\n", - ac_len,the_as->name.len,the_as->name.s); - ac_cancel(the_as,processor_id,flags,the_as->ac_buffer.s+10,ac_len-10); - break; - case SL_MSG: - LM_DBG("Processing a STATELESS MESSAGE action from AS (length=%d): %.*s\n", - ac_len,the_as->name.len,the_as->name.s); - ac_sl_msg(the_as,processor_id,flags,the_as->ac_buffer.s+10,ac_len-10); - break; - case JAIN_PONG: - LM_DBG("Processing a PONG\n"); - ac_jain_pong(the_as,processor_id,flags,the_as->ac_buffer.s+10,ac_len-10); - break; - default: - LM_DBG("Processing an UNKNOWN TYPE action from AS (length=%d): %.*s\n", - ac_len,the_as->name.len,the_as->name.s); - break; - } - memmove(the_as->ac_buffer.s,the_as->ac_buffer.s+ac_len,(the_as->ac_buffer.len)-ac_len); - (the_as->ac_buffer.len)-=ac_len; - if(the_as->ac_buffer.len>10){ - ac_len=(the_as->ac_buffer.s[0]<<24)|(the_as->ac_buffer.s[1]<<16)|(the_as->ac_buffer.s[2]<<8)|((the_as->ac_buffer.s[3])&0xFF); - type=the_as->ac_buffer.s[4]; - processor_id=the_as->ac_buffer.s[5]; - flags=(the_as->ac_buffer.s[6]<<24)|(the_as->ac_buffer.s[7]<<16)|(the_as->ac_buffer.s[8]<<8)|((the_as->ac_buffer.s[9])&0xFF); - }else{ - return 0; - } - } - return 0; + if(use_stats) + stats_reply(); + if(ac_len > AS_BUF_SIZE) { + LM_WARN("action too big (%d)!!! should be skipped and" + " an error returned!\n", + ac_len); + return -1; + } + while(the_as->ac_buffer.len >= ac_len) { + LM_DBG("Processing action %d bytes long\n", ac_len); + switch(type) { + case REPLY_PROV: + case REPLY_FIN: + LM_DBG("Processing a REPLY action from AS (length=%d): %.*s\n", + ac_len, the_as->name.len, the_as->name.s); + ac_reply(the_as, processor_id, flags, the_as->ac_buffer.s + 10, + ac_len - 10); + break; + case UAC_REQ: + LM_DBG("Processing an UAC REQUEST action from AS (length=%d): " + "%.*s\n", + ac_len, the_as->name.len, the_as->name.s); + ac_uac_req(the_as, processor_id, flags, + the_as->ac_buffer.s + 10, ac_len - 10); + break; + case AC_CANCEL: + LM_DBG("Processing a CANCEL REQUEST action from AS " + "(length=%d): %.*s\n", + ac_len, the_as->name.len, the_as->name.s); + ac_cancel(the_as, processor_id, flags, the_as->ac_buffer.s + 10, + ac_len - 10); + break; + case SL_MSG: + LM_DBG("Processing a STATELESS MESSAGE action from AS " + "(length=%d): %.*s\n", + ac_len, the_as->name.len, the_as->name.s); + ac_sl_msg(the_as, processor_id, flags, the_as->ac_buffer.s + 10, + ac_len - 10); + break; + case JAIN_PONG: + LM_DBG("Processing a PONG\n"); + ac_jain_pong(the_as, processor_id, flags, + the_as->ac_buffer.s + 10, ac_len - 10); + break; + default: + LM_DBG("Processing an UNKNOWN TYPE action from AS (length=%d): " + "%.*s\n", + ac_len, the_as->name.len, the_as->name.s); + break; + } + memmove(the_as->ac_buffer.s, the_as->ac_buffer.s + ac_len, + (the_as->ac_buffer.len) - ac_len); + (the_as->ac_buffer.len) -= ac_len; + if(the_as->ac_buffer.len > 10) { + ac_len = (the_as->ac_buffer.s[0] << 24) + | (the_as->ac_buffer.s[1] << 16) + | (the_as->ac_buffer.s[2] << 8) + | ((the_as->ac_buffer.s[3]) & 0xFF); + type = the_as->ac_buffer.s[4]; + processor_id = the_as->ac_buffer.s[5]; + flags = (the_as->ac_buffer.s[6] << 24) + | (the_as->ac_buffer.s[7] << 16) + | (the_as->ac_buffer.s[8] << 8) + | ((the_as->ac_buffer.s[9]) & 0xFF); + } else { + return 0; + } + } + return 0; } -static inline int ac_jain_pong(as_p the_as,unsigned char processor_id,unsigned int flags,char *action,int len) +static inline int ac_jain_pong(as_p the_as, unsigned char processor_id, + unsigned int flags, char *action, int len) { - unsigned int seqno; - int k; - k=0; - net2hostL(seqno,action,k); - process_pong(&the_as->jain_pings,seqno); - return 0; + unsigned int seqno; + int k; + k = 0; + net2hostL(seqno, action, k); + process_pong(&the_as->jain_pings, seqno); + return 0; } -int process_pong(struct ha *the_table,unsigned int seqno) +int process_pong(struct ha *the_table, unsigned int seqno) { - int i,k,elapsed; - struct ping *tmp; - struct timeval now; - - gettimeofday(&now,NULL); - tmp=NULL; - if(the_table->count==0) - return 0; - lock_get(the_table->mutex); - print_pingtable(the_table,-1,0); - for(i=0;icount;i++){ - k=(the_table->begin+i)%the_table->size; - tmp=the_table->pings+k; - if(tmp->id == seqno){ - elapsed=(now.tv_sec-tmp->sent.tv_sec)*1000+(now.tv_usec-tmp->sent.tv_usec)/1000; - LM_DBG("Ping-Pong delay: %d (timeout was:%d)\n",elapsed,the_table->timeout); - if(elapsed>the_table->timeout){ - /*if this ping has timed out, all the more-ancient pings will also be + int i, k, elapsed; + struct ping *tmp; + struct timeval now; + + gettimeofday(&now, NULL); + tmp = NULL; + if(the_table->count == 0) + return 0; + lock_get(the_table->mutex); + print_pingtable(the_table, -1, 0); + for(i = 0; i < the_table->count; i++) { + k = (the_table->begin + i) % the_table->size; + tmp = the_table->pings + k; + if(tmp->id == seqno) { + elapsed = (now.tv_sec - tmp->sent.tv_sec) * 1000 + + (now.tv_usec - tmp->sent.tv_usec) / 1000; + LM_DBG("Ping-Pong delay: %d (timeout was:%d)\n", elapsed, + the_table->timeout); + if(elapsed > the_table->timeout) { + /*if this ping has timed out, all the more-ancient pings will also be * timed out*/ - the_table->timed_out_pings+=i; - }/*anyway, when we find a ping in the table, we remove all the pings that are more + the_table->timed_out_pings += i; + } /*anyway, when we find a ping in the table, we remove all the pings that are more ancient (if there are any..)*/ - the_table->count-=(i+1); - the_table->begin=(k+1)%the_table->size; - break; - } - } - lock_release(the_table->mutex); - return 0; + the_table->count -= (i + 1); + the_table->begin = (k + 1) % the_table->size; + break; + } + } + lock_release(the_table->mutex); + return 0; } @@ -393,59 +427,64 @@ int process_pong(struct ha *the_table,unsigned int seqno) * Returns: * */ -int ac_cancel(as_p the_as,unsigned char processor_id,unsigned int flags,char *action,int len) +int ac_cancel(as_p the_as, unsigned char processor_id, unsigned int flags, + char *action, int len) { - unsigned int ret,cancelled_hashIdx,cancelled_label,i; - struct sip_msg *my_msg; - struct as_uac_param *the_param; - struct cell* t_invite; - int k,retval,uac_id; - str headers,body; + unsigned int ret, cancelled_hashIdx, cancelled_label, i; + struct sip_msg *my_msg; + struct as_uac_param *the_param; + struct cell *t_invite; + int k, retval, uac_id; + str headers, body; - body.s=headers.s=NULL; - my_msg=NULL; - the_param=NULL; - i=k=0; + body.s = headers.s = NULL; + my_msg = NULL; + the_param = NULL; + i = k = 0; - net2hostL(uac_id,action,k); + net2hostL(uac_id, action, k); - net2hostL(cancelled_hashIdx,action,k); - net2hostL(cancelled_label,action,k); + net2hostL(cancelled_hashIdx, action, k); + net2hostL(cancelled_label, action, k); - if(!(headers.s=pkg_malloc(MAX_HEADER))){ - LM_ERR("Out of Memory!!"); - goto error; - } - headers.len=0; - if(!(my_msg=pkg_malloc(sizeof(struct sip_msg)))){ - LM_ERR("out of memory!\n"); - goto error; - } - memset(my_msg,0,sizeof(struct sip_msg)); - my_msg->buf=action+k; - my_msg->len=len-k; - LM_DBG("Action UAC Message: uac_id:%d processor_id=%d, message:[%.*s]\n", - uac_id,processor_id,len-4,&action[4]); - if(parse_msg(action+k,len-k,my_msg)<0){ - LM_ERR("parsing sip_msg"); - goto error; - } - if(my_msg->first_line.type==SIP_REPLY){ - LM_ERR("trying to create a UAC with a SIP response!!\n"); - goto error; - } - if(parse_headers(my_msg,HDR_EOH_F,0)==-1){ - LM_ERR("parsing headers\n"); - goto error; - } - if(0>(headers.len=extract_allowed_headers(my_msg,1,-1,HDR_CONTENTLENGTH_F|HDR_ROUTE_F|HDR_TO_F|HDR_FROM_F|HDR_CALLID_F|HDR_CSEQ_F,headers.s,MAX_HEADER))) { - LM_ERR("Unable to extract allowed headers!!\n"); - goto error; - } - if(flags & SPIRAL_FLAG){ - memcpy(headers.s+headers.len,SPIRAL_HDR CRLF,SPIRAL_HDR_LEN + CRLF_LEN); - headers.len+=SPIRAL_HDR_LEN+CRLF_LEN; - /*headers.s[headers.len]=0; + if(!(headers.s = pkg_malloc(MAX_HEADER))) { + LM_ERR("Out of Memory!!"); + goto error; + } + headers.len = 0; + if(!(my_msg = pkg_malloc(sizeof(struct sip_msg)))) { + LM_ERR("out of memory!\n"); + goto error; + } + memset(my_msg, 0, sizeof(struct sip_msg)); + my_msg->buf = action + k; + my_msg->len = len - k; + LM_DBG("Action UAC Message: uac_id:%d processor_id=%d, message:[%.*s]\n", + uac_id, processor_id, len - 4, &action[4]); + if(parse_msg(action + k, len - k, my_msg) < 0) { + LM_ERR("parsing sip_msg"); + goto error; + } + if(my_msg->first_line.type == SIP_REPLY) { + LM_ERR("trying to create a UAC with a SIP response!!\n"); + goto error; + } + if(parse_headers(my_msg, HDR_EOH_F, 0) == -1) { + LM_ERR("parsing headers\n"); + goto error; + } + if(0 > (headers.len = extract_allowed_headers(my_msg, 1, -1, + HDR_CONTENTLENGTH_F | HDR_ROUTE_F | HDR_TO_F | HDR_FROM_F + | HDR_CALLID_F | HDR_CSEQ_F, + headers.s, MAX_HEADER))) { + LM_ERR("Unable to extract allowed headers!!\n"); + goto error; + } + if(flags & SPIRAL_FLAG) { + memcpy(headers.s + headers.len, SPIRAL_HDR CRLF, + SPIRAL_HDR_LEN + CRLF_LEN); + headers.len += SPIRAL_HDR_LEN + CRLF_LEN; + /*headers.s[headers.len]=0; fake_uri.s=pkg_malloc(200); fake_uri.len=print_local_uri(the_as,processor_id,fake_uri.s,200); @@ -454,186 +493,191 @@ int ac_cancel(as_p the_as,unsigned char processor_id,unsigned int flags,char *ac goto error; } my_dlg->hooks.next_hop=&fake_uri;*/ - } + } - headers.s[headers.len]=0; + headers.s[headers.len] = 0; - /*let's get the body*/ - i=(unsigned int)get_content_length(my_msg); - if(i!=0){ - if(!(body.s=pkg_malloc(i))){ - LM_ERR("Out of Memory!"); - goto error; - } - memcpy(body.s,get_body(my_msg),i); - body.len=i; - LM_DBG("Trying to construct a Sip Request with: body:%d[%s]" - " headers:%d[%s]\n", body.len,body.s,headers.len,headers.s); - }else{ - body.s=NULL; - body.len=0; - } + /*let's get the body*/ + i = (unsigned int)get_content_length(my_msg); + if(i != 0) { + if(!(body.s = pkg_malloc(i))) { + LM_ERR("Out of Memory!"); + goto error; + } + memcpy(body.s, get_body(my_msg), i); + body.len = i; + LM_DBG("Trying to construct a Sip Request with: body:%d[%s]" + " headers:%d[%s]\n", + body.len, body.s, headers.len, headers.s); + } else { + body.s = NULL; + body.len = 0; + } - if(!(the_param=shm_malloc(sizeof(struct as_uac_param)))){ - LM_ERR("no more share memory\n"); - goto error; - } + if(!(the_param = shm_malloc(sizeof(struct as_uac_param)))) { + LM_ERR("no more share memory\n"); + goto error; + } - if(seas_f.tmb.t_lookup_ident(&t_invite,cancelled_hashIdx,cancelled_label)<0){ + if(seas_f.tmb.t_lookup_ident(&t_invite, cancelled_hashIdx, cancelled_label) + < 0) { LM_ERR("failed to t_lookup_ident hash_idx=%d," - "label=%d\n", cancelled_hashIdx,cancelled_label); + "label=%d\n", + cancelled_hashIdx, cancelled_label); goto error; } seas_f.tmb.unref_cell(t_invite); - the_param->who=my_as; - the_param->uac_id=uac_id; - the_param->processor_id=processor_id; - the_param->destroy_cb_set=0; - - /* registers TMCB_RESPONSE_IN|TMCB_LOCAL_COMPLETED tm callbacks */ - ret=seas_f.tmb.t_cancel_uac(&headers,&body,cancelled_hashIdx,cancelled_label,uac_cb,(void*)the_param); - if (ret == 0) { - LM_ERR( "t_cancel_uac failed\n"); - as_action_fail_resp(uac_id,SE_CANCEL,SE_CANCEL_MSG,SE_CANCEL_MSG_LEN); - goto error; - }else{ - the_param->label=ret; - } + the_param->who = my_as; + the_param->uac_id = uac_id; + the_param->processor_id = processor_id; + the_param->destroy_cb_set = 0; + + /* registers TMCB_RESPONSE_IN|TMCB_LOCAL_COMPLETED tm callbacks */ + ret = seas_f.tmb.t_cancel_uac(&headers, &body, cancelled_hashIdx, + cancelled_label, uac_cb, (void *)the_param); + if(ret == 0) { + LM_ERR("t_cancel_uac failed\n"); + as_action_fail_resp( + uac_id, SE_CANCEL, SE_CANCEL_MSG, SE_CANCEL_MSG_LEN); + goto error; + } else { + the_param->label = ret; + } seas_f.tmb.unref_cell(t_invite); - retval=0; - goto exit; + retval = 0; + goto exit; error: - retval = -1; - if(the_param) - shm_free(the_param); + retval = -1; + if(the_param) + shm_free(the_param); exit: - if(headers.s) - pkg_free(headers.s); - if(body.s) - pkg_free(body.s); - if(my_msg){ - if(my_msg->headers) - free_hdr_field_lst(my_msg->headers); - pkg_free(my_msg); - } - return retval; + if(headers.s) + pkg_free(headers.s); + if(body.s) + pkg_free(body.s); + if(my_msg) { + if(my_msg->headers) + free_hdr_field_lst(my_msg->headers); + pkg_free(my_msg); + } + return retval; } -int recordroute_diff(struct sip_msg *req,struct sip_msg *resp) +int recordroute_diff(struct sip_msg *req, struct sip_msg *resp) { - struct hdr_field *hf; - rr_t *rr1; - int i,j,k; - i=j=k=0; - /* count how many record-route bodies come in the response*/ - /* this does not work, I think because of siblings + struct hdr_field *hf; + rr_t *rr1; + int i, j, k; + i = j = k = 0; + /* count how many record-route bodies come in the response*/ + /* this does not work, I think because of siblings for(hf=resp->record_route;hf;hf=hf->sibling,j=0){ */ - for(hf=resp->headers;hf;hf=hf->next,j=0){ - if(hf->type != HDR_RECORDROUTE_T) - continue; - if(!hf->parsed){ - if(0>parse_rr(hf)) - goto error; - j=1; - } - for(rr1=hf->parsed;rr1;rr1=rr1->next){ - i++; - } - if(j){ - free_rr((rr_t**)(void*)&hf->parsed); - hf->parsed=NULL; - } - } - /* + for(hf = resp->headers; hf; hf = hf->next, j = 0) { + if(hf->type != HDR_RECORDROUTE_T) + continue; + if(!hf->parsed) { + if(0 > parse_rr(hf)) + goto error; + j = 1; + } + for(rr1 = hf->parsed; rr1; rr1 = rr1->next) { + i++; + } + if(j) { + free_rr((rr_t **)(void *)&hf->parsed); + hf->parsed = NULL; + } + } + /* for(hf=req->record_route;hf;hf=hf->sibling,j=0){ */ - for(hf=req->headers;hf;hf=hf->next,j=0){ - if(hf->type != HDR_RECORDROUTE_T) - continue; - if(!hf->parsed){ - if(0>parse_rr(hf)) - goto error; - j=1; - } - for(rr1=hf->parsed;rr1;rr1=rr1->next){ - k++; - } - if(j){ - free_rr((rr_t**)(void*)&hf->parsed); - hf->parsed=NULL; - } - } - return i-k; + for(hf = req->headers; hf; hf = hf->next, j = 0) { + if(hf->type != HDR_RECORDROUTE_T) + continue; + if(!hf->parsed) { + if(0 > parse_rr(hf)) + goto error; + j = 1; + } + for(rr1 = hf->parsed; rr1; rr1 = rr1->next) { + k++; + } + if(j) { + free_rr((rr_t **)(void *)&hf->parsed); + hf->parsed = NULL; + } + } + return i - k; error: - return -1; + return -1; } -int via_diff(struct sip_msg *req,struct sip_msg *resp) +int via_diff(struct sip_msg *req, struct sip_msg *resp) { - struct hdr_field *hf; - struct via_body *vb; - int i,j,k; - - i=j=k=0; - /* count how many via bodies come in the response*/ - for(hf=resp->h_via1;hf;hf=next_sibling_hdr(hf)){ - if(!hf->parsed){ - if((vb=pkg_malloc(sizeof(struct via_body)))==0){ - LM_ERR("Out of mem in via_diff!!\n"); - return -1; - } - memset(vb,0,sizeof(struct via_body)); - if(parse_via(hf->body.s,hf->body.s+hf->body.len+1,vb)==0){ - LM_ERR("Unable to parse via in via_diff!\n"); - pkg_free(vb); - return -1; - } - hf->parsed=vb; - j=1; - } - for(vb=hf->parsed;vb;vb=vb->next){ - i++; - } - if(j){ - free_via_list((struct via_body*)hf->parsed); - hf->parsed=NULL; - j=0; - } - } - j=0; - /* count how many via bodies were in the orig. request*/ - for(hf=req->h_via1;hf;hf=next_sibling_hdr(hf)){ - if(!hf->parsed){ - if((vb=pkg_malloc(sizeof(struct via_body)))==0){ - goto error; - } - memset(vb,0,sizeof(struct via_body)); - if(parse_via(hf->body.s,hf->body.s+hf->body.len+1,vb)==0){ - goto error; - } - hf->parsed=vb; - j=1; - } - for(vb=hf->parsed;vb;vb=vb->next){ - k++; - } - if(j){ - free_via_list((struct via_body*)hf->parsed); - hf->parsed=NULL; - j=0; - } - } - return i-k; + struct hdr_field *hf; + struct via_body *vb; + int i, j, k; + + i = j = k = 0; + /* count how many via bodies come in the response*/ + for(hf = resp->h_via1; hf; hf = next_sibling_hdr(hf)) { + if(!hf->parsed) { + if((vb = pkg_malloc(sizeof(struct via_body))) == 0) { + LM_ERR("Out of mem in via_diff!!\n"); + return -1; + } + memset(vb, 0, sizeof(struct via_body)); + if(parse_via(hf->body.s, hf->body.s + hf->body.len + 1, vb) == 0) { + LM_ERR("Unable to parse via in via_diff!\n"); + pkg_free(vb); + return -1; + } + hf->parsed = vb; + j = 1; + } + for(vb = hf->parsed; vb; vb = vb->next) { + i++; + } + if(j) { + free_via_list((struct via_body *)hf->parsed); + hf->parsed = NULL; + j = 0; + } + } + j = 0; + /* count how many via bodies were in the orig. request*/ + for(hf = req->h_via1; hf; hf = next_sibling_hdr(hf)) { + if(!hf->parsed) { + if((vb = pkg_malloc(sizeof(struct via_body))) == 0) { + goto error; + } + memset(vb, 0, sizeof(struct via_body)); + if(parse_via(hf->body.s, hf->body.s + hf->body.len + 1, vb) == 0) { + goto error; + } + hf->parsed = vb; + j = 1; + } + for(vb = hf->parsed; vb; vb = vb->next) { + k++; + } + if(j) { + free_via_list((struct via_body *)hf->parsed); + hf->parsed = NULL; + j = 0; + } + } + return i - k; error: - return -1; + return -1; } static void param_free(void *param) { - shm_free(param); + shm_free(param); } /** * ac_reply: UAS transaction Reply action. It replies to an incoming request with a response. @@ -645,141 +689,157 @@ static void param_free(void *param) * * Returns: what */ -int ac_reply(as_p the_as,unsigned char processor_id,unsigned int flags,char *action,int len) +int ac_reply(as_p the_as, unsigned char processor_id, unsigned int flags, + char *action, int len) { - unsigned int hash_index,label,contentlength; - struct cell *c=NULL; - struct sip_msg *my_msg; - struct to_body *tb; - str new_header,body,totag; - char *ttag; - int i,k,retval; - static char headers[MAX_HEADER]; - struct as_uac_param *the_param; - - contentlength=0; - ttag=NULL; - my_msg=NULL; - i=k=0; - the_param=NULL; - - net2hostL(hash_index,action,k); - net2hostL(label,action,k); - - if(seas_f.tmb.t_lookup_ident(&c,hash_index,label)<0){ - LM_ERR("Failed to t_lookup_ident hash_idx=%d,label=%d\n",hash_index,label); - goto error; - } - if(use_stats) - action_stat(c); - if(c->uas.status>=200){ - LM_ERR("ac_reply: trying to reply to a \"%.*s\" transaction" - "that is already in completed state\n",REQ_LINE(c->uas.request).method.len,REQ_LINE(c->uas.request).method.s); - goto error; - } - if (!(my_msg=parse_ac_msg(HDR_EOH_F,action+k,len-k))) { - LM_ERR("Failed to parse_ac_msg hash_idx=%d,label=%d\n",hash_index,label); - goto error; - } - tb=(struct to_body*)my_msg->to->parsed; - if(tb->tag_value.s && tb->tag_value.len){ - totag=tb->tag_value; - }else{ - totag.s=NULL; - totag.len=0; - } - LM_DBG("Using totag=[%.*s]\n",totag.len,totag.s); - if(my_msg->content_length) - contentlength=(unsigned int)(long)my_msg->content_length->parsed; - if(0>(i=recordroute_diff(c->uas.request,my_msg))){/*not likely..*/ - LM_DBG("Seems that request had more RecordRoutes than response...\n"); - /* This prevents host->proxy->host from working. TODO review recordroute_diff code. + unsigned int hash_index, label, contentlength; + struct cell *c = NULL; + struct sip_msg *my_msg; + struct to_body *tb; + str new_header, body, totag; + char *ttag; + int i, k, retval; + static char headers[MAX_HEADER]; + struct as_uac_param *the_param; + + contentlength = 0; + ttag = NULL; + my_msg = NULL; + i = k = 0; + the_param = NULL; + + net2hostL(hash_index, action, k); + net2hostL(label, action, k); + + if(seas_f.tmb.t_lookup_ident(&c, hash_index, label) < 0) { + LM_ERR("Failed to t_lookup_ident hash_idx=%d,label=%d\n", hash_index, + label); + goto error; + } + if(use_stats) + action_stat(c); + if(c->uas.status >= 200) { + LM_ERR("ac_reply: trying to reply to a \"%.*s\" transaction" + "that is already in completed state\n", + REQ_LINE(c->uas.request).method.len, + REQ_LINE(c->uas.request).method.s); + goto error; + } + if(!(my_msg = parse_ac_msg(HDR_EOH_F, action + k, len - k))) { + LM_ERR("Failed to parse_ac_msg hash_idx=%d,label=%d\n", hash_index, + label); + goto error; + } + tb = (struct to_body *)my_msg->to->parsed; + if(tb->tag_value.s && tb->tag_value.len) { + totag = tb->tag_value; + } else { + totag.s = NULL; + totag.len = 0; + } + LM_DBG("Using totag=[%.*s]\n", totag.len, totag.s); + if(my_msg->content_length) + contentlength = (unsigned int)(long)my_msg->content_length->parsed; + if(0 > (i = recordroute_diff(c->uas.request, my_msg))) { /*not likely..*/ + LM_DBG("Seems that request had more RecordRoutes than response...\n"); + /* This prevents host->proxy->host from working. TODO review recordroute_diff code. goto error; */ - }else - LM_DBG("Recordroute Diff = %d\n",i); - - if(0>(i=extract_allowed_headers(my_msg,0,i,HDR_VIA_F|HDR_TO_F|HDR_FROM_F|HDR_CSEQ_F|HDR_CALLID_F|HDR_CONTENTLENGTH_F,headers,MAX_HEADER))){ - LM_ERR("ac_reply() filtering headers !\n"); - goto error; - } - headers[i]=0; - new_header.s=headers; - new_header.len=i; + } else + LM_DBG("Recordroute Diff = %d\n", i); + + if(0 > (i = extract_allowed_headers(my_msg, 0, i, + HDR_VIA_F | HDR_TO_F | HDR_FROM_F | HDR_CSEQ_F + | HDR_CALLID_F | HDR_CONTENTLENGTH_F, + headers, MAX_HEADER))) { + LM_ERR("ac_reply() filtering headers !\n"); + goto error; + } + headers[i] = 0; + new_header.s = headers; + new_header.len = i; - /* If it is INVITE and response is success (>=200 && <300), we mark it as local so that + /* If it is INVITE and response is success (>=200 && <300), we mark it as local so that * SER does NOT retransmit the final response (by default, SER retransmit local UAS final * responses...*/ - if(is_invite(c) && my_msg->first_line.u.reply.statuscode>=200 && my_msg->first_line.u.reply.statuscode<300){ - c->flags |= T_IS_LOCAL_FLAG; - if(!(the_param=shm_malloc(sizeof(struct as_uac_param)))){ - LM_ERR("no more share memory\n"); - goto error; - } - the_param->processor_id=processor_id; - the_param->who=my_as; - the_param->destroy_cb_set=0; - if (seas_f.tmb.register_tmcb( 0, c, TMCB_E2EACK_IN,uas_e2e_ack_cb, the_param,¶m_free)<=0) { - LM_ERR("cannot register additional callbacks\n"); - goto error; - } - } - /*WARNING casting unsigned int to int*/ - body.len=contentlength; - body.s=get_body(my_msg); - - LM_DBG("Trying to construct a SipReply with: ReasonPhrase:[%.*s] body:[%.*s] headers:[%.*s] totag:[%.*s]\n",\ - my_msg->first_line.u.reply.reason.len,my_msg->first_line.u.reply.reason.s,\ - body.len,body.s,new_header.len,new_header.s,totag.len,totag.s); - /* t_reply_with_body un-ref-counts the transaction, so don't use it anymore*/ - if(seas_f.tmb.t_reply_with_body(c,my_msg->first_line.u.reply.statuscode,&(my_msg->first_line.u.reply.reason),&body,&new_header,&totag)<0){ - LM_ERR("Failed to t_reply\n"); - goto error; - } - retval=0; - goto exit; + if(is_invite(c) && my_msg->first_line.u.reply.statuscode >= 200 + && my_msg->first_line.u.reply.statuscode < 300) { + c->flags |= T_IS_LOCAL_FLAG; + if(!(the_param = shm_malloc(sizeof(struct as_uac_param)))) { + LM_ERR("no more share memory\n"); + goto error; + } + the_param->processor_id = processor_id; + the_param->who = my_as; + the_param->destroy_cb_set = 0; + if(seas_f.tmb.register_tmcb( + 0, c, TMCB_E2EACK_IN, uas_e2e_ack_cb, the_param, ¶m_free) + <= 0) { + LM_ERR("cannot register additional callbacks\n"); + goto error; + } + } + /*WARNING casting unsigned int to int*/ + body.len = contentlength; + body.s = get_body(my_msg); + + LM_DBG("Trying to construct a SipReply with: ReasonPhrase:[%.*s] " + "body:[%.*s] headers:[%.*s] totag:[%.*s]\n", + my_msg->first_line.u.reply.reason.len, + my_msg->first_line.u.reply.reason.s, body.len, body.s, + new_header.len, new_header.s, totag.len, totag.s); + /* t_reply_with_body un-ref-counts the transaction, so don't use it anymore*/ + if(seas_f.tmb.t_reply_with_body(c, my_msg->first_line.u.reply.statuscode, + &(my_msg->first_line.u.reply.reason), &body, &new_header, &totag) + < 0) { + LM_ERR("Failed to t_reply\n"); + goto error; + } + retval = 0; + goto exit; error: - retval = -1; - if(c) - seas_f.tmb.unref_cell(c); - if(the_param) - shm_free(the_param); + retval = -1; + if(c) + seas_f.tmb.unref_cell(c); + if(the_param) + shm_free(the_param); exit: - if(ttag) - pkg_free(ttag); - if(my_msg){ - free_sip_msg_lite(my_msg); - pkg_free(my_msg); - } - return retval; + if(ttag) + pkg_free(ttag); + if(my_msg) { + free_sip_msg_lite(my_msg); + pkg_free(my_msg); + } + return retval; } -static inline struct sip_msg *parse_ac_msg(hdr_flags_t flags,char *start,int len) +static inline struct sip_msg *parse_ac_msg( + hdr_flags_t flags, char *start, int len) { - struct sip_msg *my_msg; - my_msg=NULL; - if(!(my_msg=pkg_malloc(sizeof(struct sip_msg)))){ - LM_ERR("ac_reply: out of memory!\n"); - goto error; - } - memset(my_msg,0,sizeof(struct sip_msg)); - my_msg->buf=start; - my_msg->len=len; - LM_DBG("Action Message:[%.*s]\n",len,start); - if(0>parse_msg(start,len,my_msg)){ - LM_ERR("parse_ac_msg: parsing sip_msg"); - goto error; - } - if(0>parse_headers(my_msg,flags,0)){ - LM_ERR("parse_ac_msg: parsing headers\n"); - goto error; - } - return my_msg; + struct sip_msg *my_msg; + my_msg = NULL; + if(!(my_msg = pkg_malloc(sizeof(struct sip_msg)))) { + LM_ERR("ac_reply: out of memory!\n"); + goto error; + } + memset(my_msg, 0, sizeof(struct sip_msg)); + my_msg->buf = start; + my_msg->len = len; + LM_DBG("Action Message:[%.*s]\n", len, start); + if(0 > parse_msg(start, len, my_msg)) { + LM_ERR("parse_ac_msg: parsing sip_msg"); + goto error; + } + if(0 > parse_headers(my_msg, flags, 0)) { + LM_ERR("parse_ac_msg: parsing headers\n"); + goto error; + } + return my_msg; error: - if(my_msg){ - free_sip_msg_lite(my_msg); - pkg_free(my_msg); - } - return NULL; + if(my_msg) { + free_sip_msg_lite(my_msg); + pkg_free(my_msg); + } + return NULL; } /* Actions are composed as follows: @@ -790,92 +850,108 @@ static inline struct sip_msg *parse_ac_msg(hdr_flags_t flags,char *start,int len * use static buffers. * */ -int ac_sl_msg(as_p the_as,unsigned char processor_id,unsigned int flags,char *action,int len) +int ac_sl_msg(as_p the_as, unsigned char processor_id, unsigned int flags, + char *action, int len) { - struct sip_msg *my_msg; - str *uri; - struct proxy_l *proxy; - rr_t *my_route; - int k,retval; - //enum sip_protos proto; + struct sip_msg *my_msg; + str *uri; + struct proxy_l *proxy; + rr_t *my_route; + int k, retval; + //enum sip_protos proto; - my_msg=NULL; - k=0; + my_msg = NULL; + k = 0; - proxy=0; + proxy = 0; - if(!(my_msg = parse_ac_msg(HDR_EOH_F,action+k,len-k))){ - LM_ERR("out of memory!\n"); - goto error; - } - if(my_msg->first_line.type == SIP_REQUEST) - LM_DBG("forwarding request:\"%.*s\" statelessly \n",my_msg->first_line.u.request.method.len+1+\ - my_msg->first_line.u.request.uri.len,my_msg->first_line.u.request.method.s); - else - LM_DBG("forwarding reply:\"%.*s\" statelessly \n",my_msg->first_line.u.reply.status.len+1+\ - my_msg->first_line.u.reply.reason.len,my_msg->first_line.u.reply.status.s); - - if (my_msg->route) { - if (parse_rr(my_msg->route) < 0) { - LM_ERR( "Error while parsing Route body\n"); - goto error; - } - my_route = (rr_t*)my_msg->route->parsed; - uri=&(my_route->nameaddr.uri); - }else{ - uri = GET_RURI(my_msg); - } - set_force_socket(my_msg, grep_sock_info(&my_msg->via1->host, - my_msg->via1->port, - my_msg->via1->proto) ); - /* or also could be: + if(!(my_msg = parse_ac_msg(HDR_EOH_F, action + k, len - k))) { + LM_ERR("out of memory!\n"); + goto error; + } + if(my_msg->first_line.type == SIP_REQUEST) + LM_DBG("forwarding request:\"%.*s\" statelessly \n", + my_msg->first_line.u.request.method.len + 1 + + my_msg->first_line.u.request.uri.len, + my_msg->first_line.u.request.method.s); + else + LM_DBG("forwarding reply:\"%.*s\" statelessly \n", + my_msg->first_line.u.reply.status.len + 1 + + my_msg->first_line.u.reply.reason.len, + my_msg->first_line.u.reply.status.s); + + if(my_msg->route) { + if(parse_rr(my_msg->route) < 0) { + LM_ERR("Error while parsing Route body\n"); + goto error; + } + my_route = (rr_t *)my_msg->route->parsed; + uri = &(my_route->nameaddr.uri); + } else { + uri = GET_RURI(my_msg); + } + set_force_socket(my_msg, grep_sock_info(&my_msg->via1->host, + my_msg->via1->port, my_msg->via1->proto)); + /* or also could be: my_msg->force_send_socket=the_as->binds[processor_id].bind_address; not sure which is better... */ - /*proxy=uri2proxy(uri,PROTO_NONE); + /*proxy=uri2proxy(uri,PROTO_NONE); if (proxy==0) { LM_ERR("unable to create proxy from URI \n"); goto error; } proto=proxy->proto; */ - //TODO my_msg->recvd - if(0>forward_sl_request(my_msg,uri,PROTO_NONE)) - goto error; - retval=0; - goto exit; + //TODO my_msg->recvd + if(0 > forward_sl_request(my_msg, uri, PROTO_NONE)) + goto error; + retval = 0; + goto exit; error: - retval = -1; + retval = -1; exit: - if(proxy){ - free_proxy(proxy); - pkg_free(proxy); - } - if(my_msg){ - free_sip_msg_lite(my_msg); - pkg_free(my_msg); - } - return retval; + if(proxy) { + free_proxy(proxy); + pkg_free(proxy); + } + if(my_msg) { + free_sip_msg_lite(my_msg); + pkg_free(my_msg); + } + return retval; } static inline void free_sip_msg_lite(struct sip_msg *my_msg) { - if(my_msg){ - /**should do the same as in free_sip_msg() but w/o freeing my_msg->buf*/ - if (my_msg->new_uri.s) { pkg_free(my_msg->new_uri.s); my_msg->new_uri.len=0; } - if (my_msg->dst_uri.s) { pkg_free(my_msg->dst_uri.s); my_msg->dst_uri.len=0; } - if (my_msg->path_vec.s) { pkg_free(my_msg->path_vec.s);my_msg->path_vec.len=0; } - if (my_msg->headers) free_hdr_field_lst(my_msg->headers); - if (my_msg->add_rm) free_lump_list(my_msg->add_rm); - if (my_msg->body_lumps) free_lump_list(my_msg->body_lumps); - /* this is not in lump_struct.h, and anyhow it's not supposed to be any lumps + if(my_msg) { + /**should do the same as in free_sip_msg() but w/o freeing my_msg->buf*/ + if(my_msg->new_uri.s) { + pkg_free(my_msg->new_uri.s); + my_msg->new_uri.len = 0; + } + if(my_msg->dst_uri.s) { + pkg_free(my_msg->dst_uri.s); + my_msg->dst_uri.len = 0; + } + if(my_msg->path_vec.s) { + pkg_free(my_msg->path_vec.s); + my_msg->path_vec.len = 0; + } + if(my_msg->headers) + free_hdr_field_lst(my_msg->headers); + if(my_msg->add_rm) + free_lump_list(my_msg->add_rm); + if(my_msg->body_lumps) + free_lump_list(my_msg->body_lumps); + /* this is not in lump_struct.h, and anyhow it's not supposed to be any lumps * in our messages... or is it? if (my_msg->reply_lump) free_reply_lump(my_msg->reply_lump); */ - } + } } -int forward_sl_request(struct sip_msg *msg,str *uri,int proto) +int forward_sl_request(struct sip_msg *msg, str *uri, int proto) { struct dest_info dst; int ret; @@ -883,25 +959,24 @@ int forward_sl_request(struct sip_msg *msg,str *uri,int proto) ret = -1; #ifdef USE_DNS_FAILOVER - if ((uri2dst(NULL,&dst, msg, uri, proto)==0) || (dst.send_sock==0)) + if((uri2dst(NULL, &dst, msg, uri, proto) == 0) || (dst.send_sock == 0)) #else - if ((uri2dst(&dst, msg, uri, proto)==0) || (dst.send_sock==0)) + if((uri2dst(&dst, msg, uri, proto) == 0) || (dst.send_sock == 0)) #endif - { + { LM_ERR("no socket found\n"); return -1; } - LM_DBG("Sending:\n%.*s.\n", (int)msg->len,msg->buf); - if (msg_send(&dst, msg->buf,msg->len)<0){ - LM_ERR("Error sending message !!\n"); - return -1; - } + LM_DBG("Sending:\n%.*s.\n", (int)msg->len, msg->buf); + if(msg_send(&dst, msg->buf, msg->len) < 0) { + LM_ERR("Error sending message !!\n"); + return -1; + } return ret; } - /*Actions are composed as follows: * (the action length and type as always= 5 bytes) * 4:uac_id @@ -912,119 +987,128 @@ int forward_sl_request(struct sip_msg *msg,str *uri,int proto) * use static buffers. * */ -int ac_uac_req(as_p the_as,unsigned char processor_id,unsigned int flags,char *action,int len) +int ac_uac_req(as_p the_as, unsigned char processor_id, unsigned int flags, + char *action, int len) { - unsigned int cseq; - char err_buf[MAX_REASON_LEN]; - struct sip_msg *my_msg; - struct to_body *fb,*tb; - struct cseq_body *cseqb; - struct as_uac_param *the_param; - dlg_t *my_dlg; - int k,retval,uac_id,sip_error,ret,err_ret; - long clen; - str headers,body,fake_uri; - uac_req_t uac_r; - - headers.s=body.s=fake_uri.s=NULL; - my_dlg=NULL; - my_msg=NULL; - the_param=NULL; - k=clen=0; - - net2hostL(uac_id,action,k); - - if(!(headers.s=pkg_malloc(MAX_HEADER))){ - LM_ERR("Out of Memory!!"); - goto error; - } - headers.len=0; - LM_DBG("Action UAC Message: uac_id:%d processor_id=%d\n",uac_id,processor_id); - if (!(my_msg = parse_ac_msg(HDR_EOH_F,action+k,len-k))) { - LM_ERR("out of memory!\n"); - goto error; - } - if(my_msg->first_line.type==SIP_REPLY){ - LM_ERR("trying to create a UAC with a SIP response!!\n"); - goto error; - } - if(parse_headers(my_msg,HDR_EOH_F,0)==-1){ - LM_ERR("ERROR:seas:ac_uac_req:parsing headers\n"); - goto error; - } - if(parse_from_header(my_msg)<0){ - LM_ERR("parsing from header ! \n"); - goto error; - } - if(check_transaction_quadruple(my_msg)==0){ - as_action_fail_resp(uac_id,SE_UAC,"Headers missing (to,from,call-id,cseq)?",0); - LM_ERR("Headers missing (to,from,call-id,cseq)?"); - goto error; - } - if(!(get_from(my_msg)) || !(get_from(my_msg)->tag_value.s) || - !(get_from(my_msg)->tag_value.len)){ - as_action_fail_resp(uac_id,SE_UAC,"From tag missing",0); - LM_ERR("From tag missing"); - goto error; - } - fb=my_msg->from->parsed; - tb=my_msg->to->parsed; - cseqb=my_msg->cseq->parsed; - if(0!=(str2int(&cseqb->number,&cseq))){ - LM_DBG("unable to parse CSeq\n"); - goto error; - } - if(my_msg->first_line.u.request.method_value != METHOD_ACK && - my_msg->first_line.u.request.method_value != METHOD_CANCEL) { - /** we trick req_within */ - cseq--; - } - if(seas_f.tmb.new_dlg_uac(&(my_msg->callid->body),&(fb->tag_value),cseq,\ - &(fb->uri),&(tb->uri),&my_dlg) < 0) { - as_action_fail_resp(uac_id,SE_UAC,"Error creating new dialog",0); - LM_ERR("Error while creating new dialog\n"); - goto error; - } - if(seas_f.tmb.dlg_add_extra(my_dlg,&(fb->display),&(tb->display)) < 0 ) { - as_action_fail_resp(uac_id,SE_UAC, - "Error adding the display names to the new dialog",0); - LM_ERR("failed to add display names to the new dialog\n"); - goto error; - } + unsigned int cseq; + char err_buf[MAX_REASON_LEN]; + struct sip_msg *my_msg; + struct to_body *fb, *tb; + struct cseq_body *cseqb; + struct as_uac_param *the_param; + dlg_t *my_dlg; + int k, retval, uac_id, sip_error, ret, err_ret; + long clen; + str headers, body, fake_uri; + uac_req_t uac_r; + + headers.s = body.s = fake_uri.s = NULL; + my_dlg = NULL; + my_msg = NULL; + the_param = NULL; + k = clen = 0; + + net2hostL(uac_id, action, k); + + if(!(headers.s = pkg_malloc(MAX_HEADER))) { + LM_ERR("Out of Memory!!"); + goto error; + } + headers.len = 0; + LM_DBG("Action UAC Message: uac_id:%d processor_id=%d\n", uac_id, + processor_id); + if(!(my_msg = parse_ac_msg(HDR_EOH_F, action + k, len - k))) { + LM_ERR("out of memory!\n"); + goto error; + } + if(my_msg->first_line.type == SIP_REPLY) { + LM_ERR("trying to create a UAC with a SIP response!!\n"); + goto error; + } + if(parse_headers(my_msg, HDR_EOH_F, 0) == -1) { + LM_ERR("ERROR:seas:ac_uac_req:parsing headers\n"); + goto error; + } + if(parse_from_header(my_msg) < 0) { + LM_ERR("parsing from header ! \n"); + goto error; + } + if(check_transaction_quadruple(my_msg) == 0) { + as_action_fail_resp( + uac_id, SE_UAC, "Headers missing (to,from,call-id,cseq)?", 0); + LM_ERR("Headers missing (to,from,call-id,cseq)?"); + goto error; + } + if(!(get_from(my_msg)) || !(get_from(my_msg)->tag_value.s) + || !(get_from(my_msg)->tag_value.len)) { + as_action_fail_resp(uac_id, SE_UAC, "From tag missing", 0); + LM_ERR("From tag missing"); + goto error; + } + fb = my_msg->from->parsed; + tb = my_msg->to->parsed; + cseqb = my_msg->cseq->parsed; + if(0 != (str2int(&cseqb->number, &cseq))) { + LM_DBG("unable to parse CSeq\n"); + goto error; + } + if(my_msg->first_line.u.request.method_value != METHOD_ACK + && my_msg->first_line.u.request.method_value != METHOD_CANCEL) { + /** we trick req_within */ + cseq--; + } + if(seas_f.tmb.new_dlg_uac(&(my_msg->callid->body), &(fb->tag_value), cseq, + &(fb->uri), &(tb->uri), &my_dlg) + < 0) { + as_action_fail_resp(uac_id, SE_UAC, "Error creating new dialog", 0); + LM_ERR("Error while creating new dialog\n"); + goto error; + } + if(seas_f.tmb.dlg_add_extra(my_dlg, &(fb->display), &(tb->display)) < 0) { + as_action_fail_resp(uac_id, SE_UAC, + "Error adding the display names to the new dialog", 0); + LM_ERR("failed to add display names to the new dialog\n"); + goto error; + } - if(tb->tag_value.s && tb->tag_value.len) - shm_str_dup(&my_dlg->id.rem_tag,&tb->tag_value); - /**Awful hack: to be able to set our own CSeq, from_tag and call-ID we have + if(tb->tag_value.s && tb->tag_value.len) + shm_str_dup(&my_dlg->id.rem_tag, &tb->tag_value); + /**Awful hack: to be able to set our own CSeq, from_tag and call-ID we have * to use req_within instead of req_outside (it sets its own CSeq, Call-ID * and ftag), so we have to simulate that the dialog is already in completed * state so... */ - server_signature=0; - my_dlg->state = DLG_CONFIRMED; - if(0>(headers.len=extract_allowed_headers(my_msg,1,-1,HDR_CONTENTLENGTH_F|HDR_ROUTE_F|HDR_TO_F|HDR_FROM_F|HDR_CALLID_F|HDR_CSEQ_F,headers.s,MAX_HEADER))) { - LM_ERR("Unable to extract allowed headers!!\n"); - goto error; - } - headers.s[headers.len]=0; - /*let's get the body*/ - if(my_msg->content_length) - clen=(long)get_content_length(my_msg); - if(clen!=0){ - if(!(body.s=pkg_malloc(clen))){ - LM_ERR("Out of Memory!"); - goto error; - } - memcpy(body.s,get_body(my_msg),clen); - body.len=clen; - body.s[clen]=0; - LM_DBG("Trying to construct a Sip Request with: body:%d[%.*s] headers:%d[%.*s]\n",\ - body.len,body.len,body.s,headers.len,headers.len,headers.s); - /*t_reply_with_body un-ref-counts the transaction, so don't use it anymore*/ - }else{ - body.s=NULL; - body.len=0; - } - /*Now... create the UAC !! + server_signature = 0; + my_dlg->state = DLG_CONFIRMED; + if(0 > (headers.len = extract_allowed_headers(my_msg, 1, -1, + HDR_CONTENTLENGTH_F | HDR_ROUTE_F | HDR_TO_F | HDR_FROM_F + | HDR_CALLID_F | HDR_CSEQ_F, + headers.s, MAX_HEADER))) { + LM_ERR("Unable to extract allowed headers!!\n"); + goto error; + } + headers.s[headers.len] = 0; + /*let's get the body*/ + if(my_msg->content_length) + clen = (long)get_content_length(my_msg); + if(clen != 0) { + if(!(body.s = pkg_malloc(clen))) { + LM_ERR("Out of Memory!"); + goto error; + } + memcpy(body.s, get_body(my_msg), clen); + body.len = clen; + body.s[clen] = 0; + LM_DBG("Trying to construct a Sip Request with: body:%d[%.*s] " + "headers:%d[%.*s]\n", + body.len, body.len, body.s, headers.len, headers.len, + headers.s); + /*t_reply_with_body un-ref-counts the transaction, so don't use it anymore*/ + } else { + body.s = NULL; + body.len = 0; + } + /*Now... create the UAC !! * it would be great to know the hash_index and the label that have been assigned * to our newly created cell, but t_uac does not leave any way for us to know... * only that when that transaction transitions its state (ie. a response is received, @@ -1034,156 +1118,168 @@ int ac_uac_req(as_p the_as,unsigned char processor_id,unsigned int flags,char *a * 2 pointers: one to the app_server and the other, the identifier of the UAC (uac_id). * */ - if(!(the_param=shm_malloc(sizeof(struct as_uac_param)))){ - LM_ERR("out of shared memory\n"); - goto error; - } - the_param->who=my_as; - the_param->uac_id=uac_id; - the_param->processor_id=processor_id; - the_param->destroy_cb_set=0; + if(!(the_param = shm_malloc(sizeof(struct as_uac_param)))) { + LM_ERR("out of shared memory\n"); + goto error; + } + the_param->who = my_as; + the_param->uac_id = uac_id; + the_param->processor_id = processor_id; + the_param->destroy_cb_set = 0; - shm_str_dup(&my_dlg->rem_target,&my_msg->first_line.u.request.uri); + shm_str_dup(&my_dlg->rem_target, &my_msg->first_line.u.request.uri); - if (my_msg->route) { - if (parse_rr(my_msg->route) < 0) { - LM_ERR( "Error while parsing Route body\n"); - goto error; - } - /* TODO route_set should be a shm copy of my_msg->route->parsed */ - my_dlg->route_set=(rr_t*)my_msg->route->parsed; - /** this SHOULD be: + if(my_msg->route) { + if(parse_rr(my_msg->route) < 0) { + LM_ERR("Error while parsing Route body\n"); + goto error; + } + /* TODO route_set should be a shm copy of my_msg->route->parsed */ + my_dlg->route_set = (rr_t *)my_msg->route->parsed; + /** this SHOULD be: shm_duplicate_rr(&my_dlg->route_set,my_msg->route->parsed); * but it will last more... */ - } - calculate_hooks(my_dlg); - if(flags & SPIRAL_FLAG){ - memcpy(headers.s+headers.len,SPIRAL_HDR CRLF,SPIRAL_HDR_LEN + CRLF_LEN); - headers.len+=SPIRAL_HDR_LEN+CRLF_LEN; - headers.s[headers.len]=0; - fake_uri.s=pkg_malloc(200); - fake_uri.len=print_local_uri(the_as,processor_id,fake_uri.s,200); - - if(fake_uri.len<0){ - LM_ERR("printing local uri\n"); - goto error; - } - my_dlg->hooks.next_hop=&fake_uri; - } - /* Kamailio and OpenSIPs seem to have diverged quite a bit on flags and events + } + calculate_hooks(my_dlg); + if(flags & SPIRAL_FLAG) { + memcpy(headers.s + headers.len, SPIRAL_HDR CRLF, + SPIRAL_HDR_LEN + CRLF_LEN); + headers.len += SPIRAL_HDR_LEN + CRLF_LEN; + headers.s[headers.len] = 0; + fake_uri.s = pkg_malloc(200); + fake_uri.len = print_local_uri(the_as, processor_id, fake_uri.s, 200); + + if(fake_uri.len < 0) { + LM_ERR("printing local uri\n"); + goto error; + } + my_dlg->hooks.next_hop = &fake_uri; + } + /* Kamailio and OpenSIPs seem to have diverged quite a bit on flags and events notified to UACs. Let's see if kamailio gets it right by now, if not this is a TODO: check PASS_PROVISIONAL my_dlg->T_flags=T_NO_AUTO_ACK|T_PASS_PROVISIONAL_FLAG ; this is the same as (TMCB_DONT_ACK|TMCB_LOCAL_RESPONSE_OUT) in Kamailio */ - set_uac_req(&uac_r, &(my_msg->first_line.u.request.method), &headers, - &body, my_dlg,TMCB_DONT_ACK|TMCB_LOCAL_RESPONSE_OUT, uac_cb, - (void*)the_param); - - ret=seas_f.tmb.t_request_within(&uac_r); - - /** now undo all the fakes we have put in my_dlg*/ - /*because my_dlg->route_set should be shm but we fake it (its pkg_mem)*/ - my_dlg->route_set=(rr_t *)0; - if (ret < 0) { - err_ret = err2reason_phrase(ret,&sip_error,err_buf, sizeof(err_buf), "SEAS/UAC"); - LM_ERR("failed to send the [%.*s] request\n",uac_r.method->len,uac_r.method->s); - LM_ERR("Error on request_within %s\n",err_buf ); - if(err_ret > 0) { - as_action_fail_resp(uac_id,ret,err_buf,0); - }else{ - as_action_fail_resp(uac_id,E_UNSPEC,"500 SEAS/UAC error",0); - } - goto error; - } - retval=0; - goto exit; + set_uac_req(&uac_r, &(my_msg->first_line.u.request.method), &headers, &body, + my_dlg, TMCB_DONT_ACK | TMCB_LOCAL_RESPONSE_OUT, uac_cb, + (void *)the_param); + + ret = seas_f.tmb.t_request_within(&uac_r); + + /** now undo all the fakes we have put in my_dlg*/ + /*because my_dlg->route_set should be shm but we fake it (its pkg_mem)*/ + my_dlg->route_set = (rr_t *)0; + if(ret < 0) { + err_ret = err2reason_phrase( + ret, &sip_error, err_buf, sizeof(err_buf), "SEAS/UAC"); + LM_ERR("failed to send the [%.*s] request\n", uac_r.method->len, + uac_r.method->s); + LM_ERR("Error on request_within %s\n", err_buf); + if(err_ret > 0) { + as_action_fail_resp(uac_id, ret, err_buf, 0); + } else { + as_action_fail_resp(uac_id, E_UNSPEC, "500 SEAS/UAC error", 0); + } + goto error; + } + retval = 0; + goto exit; error: - retval = -1; - if(the_param) - shm_free(the_param); + retval = -1; + if(the_param) + shm_free(the_param); exit: - seas_f.tmb.free_dlg(my_dlg); - if(headers.s) - pkg_free(headers.s); - if(body.s) - pkg_free(body.s); - if(fake_uri.s) - pkg_free(fake_uri.s); - if(my_msg){ - if(my_msg->headers) - free_hdr_field_lst(my_msg->headers); - pkg_free(my_msg); - } - return retval; + seas_f.tmb.free_dlg(my_dlg); + if(headers.s) + pkg_free(headers.s); + if(body.s) + pkg_free(body.s); + if(fake_uri.s) + pkg_free(fake_uri.s); + if(my_msg) { + if(my_msg->headers) + free_hdr_field_lst(my_msg->headers); + pkg_free(my_msg); + } + return retval; } /** * len MUST be >0 */ -int print_local_uri(as_p as,char processor_id,char *where,int len) +int print_local_uri(as_p as, char processor_id, char *where, int len) { - int i; - struct socket_info *si; - str proto; - proto.s=NULL; - proto.len=0; - for(i=0;ibound_processor[i]==processor_id) - break; - } - if(i==MAX_BINDS){ - LM_DBG("processor ID not found\n"); - return -1; - } - si=as->binds[i]; - switch(si->proto){ - case PROTO_UDP: - proto.s=""; - proto.len=0; - break; - case PROTO_TCP: - proto.s=TRANSPORT_PARAM "TCP"; - proto.len=TRANSPORT_PARAM_LEN + 3; - break; - case PROTO_TLS: - proto.s=TRANSPORT_PARAM "TLS"; - proto.len=TRANSPORT_PARAM_LEN + 3; - break; - case PROTO_SCTP: - proto.s=TRANSPORT_PARAM "SCTP"; - proto.len=TRANSPORT_PARAM_LEN + 4; - break; - case PROTO_WS: - case PROTO_WSS: - proto.s=TRANSPORT_PARAM "WS"; - proto.len=TRANSPORT_PARAM_LEN + 2; - break; - } - switch(si->address.af){ - case AF_INET: - i=snprintf(where,len,"sip:%d.%d.%d.%d:%u%.*s",si->address.u.addr[0],si->address.u.addr[1],\ - si->address.u.addr[2],si->address.u.addr[3],si->port_no,proto.len,proto.s); - break; - case AF_INET6: - i=snprintf(where,len,"sip:[%x:%x:%x:%x:%x:%x:%x:%x]:%u%.*s", htons(si->address.u.addr16[0]), htons(si->address.u.addr16[1]),\ - htons(si->address.u.addr16[2]), htons(si->address.u.addr16[3]), htons(si->address.u.addr16[4]), htons(si->address.u.addr16[5]),\ - htons(si->address.u.addr16[6]), htons(si->address.u.addr16[7]),si->port_no,proto.len,proto.s); - break; - default: - LM_ERR("address family unknown\n"); - return -1; - } - if(i>len){ - LM_ERR("Output was truncated!!\n"); - return -1; - }else if(i<0){ - LM_ERR("Error on snprintf\n"); - return i; - } - return i; + int i; + struct socket_info *si; + str proto; + proto.s = NULL; + proto.len = 0; + for(i = 0; i < MAX_BINDS; i++) { + if(as->bound_processor[i] == processor_id) + break; + } + if(i == MAX_BINDS) { + LM_DBG("processor ID not found\n"); + return -1; + } + si = as->binds[i]; + switch(si->proto) { + case PROTO_UDP: + proto.s = ""; + proto.len = 0; + break; + case PROTO_TCP: + proto.s = TRANSPORT_PARAM "TCP"; + proto.len = TRANSPORT_PARAM_LEN + 3; + break; + case PROTO_TLS: + proto.s = TRANSPORT_PARAM "TLS"; + proto.len = TRANSPORT_PARAM_LEN + 3; + break; + case PROTO_SCTP: + proto.s = TRANSPORT_PARAM "SCTP"; + proto.len = TRANSPORT_PARAM_LEN + 4; + break; + case PROTO_WS: + case PROTO_WSS: + proto.s = TRANSPORT_PARAM "WS"; + proto.len = TRANSPORT_PARAM_LEN + 2; + break; + } + switch(si->address.af) { + case AF_INET: + i = snprintf(where, len, "sip:%d.%d.%d.%d:%u%.*s", + si->address.u.addr[0], si->address.u.addr[1], + si->address.u.addr[2], si->address.u.addr[3], si->port_no, + proto.len, proto.s); + break; + case AF_INET6: + i = snprintf(where, len, "sip:[%x:%x:%x:%x:%x:%x:%x:%x]:%u%.*s", + htons(si->address.u.addr16[0]), + htons(si->address.u.addr16[1]), + htons(si->address.u.addr16[2]), + htons(si->address.u.addr16[3]), + htons(si->address.u.addr16[4]), + htons(si->address.u.addr16[5]), + htons(si->address.u.addr16[6]), + htons(si->address.u.addr16[7]), si->port_no, proto.len, + proto.s); + break; + default: + LM_ERR("address family unknown\n"); + return -1; + } + if(i > len) { + LM_ERR("Output was truncated!!\n"); + return -1; + } else if(i < 0) { + LM_ERR("Error on snprintf\n"); + return i; + } + return i; } /* !!! COPIED FROM MODULES/TM !! @@ -1197,15 +1293,15 @@ int print_local_uri(as_p as,char processor_id,char *where,int len) * _s will be modified so it should be a tmp * copy */ -void get_raw_uri(str* _s) +void get_raw_uri(str *_s) { - char* aq; + char *aq; - if (_s->s[_s->len - 1] == '>') { - aq = find_not_quoted(_s, '<'); - _s->len -= aq - _s->s + 2; - _s->s = aq + 1; - } + if(_s->s[_s->len - 1] == '>') { + aq = find_not_quoted(_s, '<'); + _s->len -= aq - _s->s + 2; + _s->s = aq + 1; + } } /* !!! COPIED FROM MODULES/TM !! * Calculate dialog hooks @@ -1215,49 +1311,55 @@ void get_raw_uri(str* _s) * Maybe a reference to the original function in TM * could be reached via handlers or whatever... */ -static inline int calculate_hooks(dlg_t* _d) +static inline int calculate_hooks(dlg_t *_d) { - str* uri; - struct sip_uri puri; - - if (_d->route_set) { - uri = &_d->route_set->nameaddr.uri; - if (parse_uri(uri->s, uri->len, &puri) < 0) { - LM_ERR( "Error while parsing URI\n"); - return -1; - } + str *uri; + struct sip_uri puri; + + if(_d->route_set) { + uri = &_d->route_set->nameaddr.uri; + if(parse_uri(uri->s, uri->len, &puri) < 0) { + LM_ERR("Error while parsing URI\n"); + return -1; + } - if (puri.lr.s) { - if (_d->rem_target.s) _d->hooks.request_uri = &_d->rem_target; - else _d->hooks.request_uri = &_d->rem_uri; - _d->hooks.next_hop = &_d->route_set->nameaddr.uri; - _d->hooks.first_route = _d->route_set; - } else { - _d->hooks.request_uri = &_d->route_set->nameaddr.uri; - _d->hooks.next_hop = _d->hooks.request_uri; - _d->hooks.first_route = _d->route_set->next; - _d->hooks.last_route = &_d->rem_target; - } - } else { - if (_d->rem_target.s) _d->hooks.request_uri = &_d->rem_target; - else _d->hooks.request_uri = &_d->rem_uri; - _d->hooks.next_hop = _d->hooks.request_uri; - } + if(puri.lr.s) { + if(_d->rem_target.s) + _d->hooks.request_uri = &_d->rem_target; + else + _d->hooks.request_uri = &_d->rem_uri; + _d->hooks.next_hop = &_d->route_set->nameaddr.uri; + _d->hooks.first_route = _d->route_set; + } else { + _d->hooks.request_uri = &_d->route_set->nameaddr.uri; + _d->hooks.next_hop = _d->hooks.request_uri; + _d->hooks.first_route = _d->route_set->next; + _d->hooks.last_route = &_d->rem_target; + } + } else { + if(_d->rem_target.s) + _d->hooks.request_uri = &_d->rem_target; + else + _d->hooks.request_uri = &_d->rem_uri; + _d->hooks.next_hop = _d->hooks.request_uri; + } - if ((_d->hooks.request_uri) && (_d->hooks.request_uri->s) && (_d->hooks.request_uri->len)) { - _d->hooks.ru.s = _d->hooks.request_uri->s; - _d->hooks.ru.len = _d->hooks.request_uri->len; - _d->hooks.request_uri = &_d->hooks.ru; - get_raw_uri(_d->hooks.request_uri); - } - if ((_d->hooks.next_hop) && (_d->hooks.next_hop->s) && (_d->hooks.next_hop->len)) { - _d->hooks.nh.s = _d->hooks.next_hop->s; - _d->hooks.nh.len = _d->hooks.next_hop->len; - _d->hooks.next_hop = &_d->hooks.nh; - get_raw_uri(_d->hooks.next_hop); - } + if((_d->hooks.request_uri) && (_d->hooks.request_uri->s) + && (_d->hooks.request_uri->len)) { + _d->hooks.ru.s = _d->hooks.request_uri->s; + _d->hooks.ru.len = _d->hooks.request_uri->len; + _d->hooks.request_uri = &_d->hooks.ru; + get_raw_uri(_d->hooks.request_uri); + } + if((_d->hooks.next_hop) && (_d->hooks.next_hop->s) + && (_d->hooks.next_hop->len)) { + _d->hooks.nh.s = _d->hooks.next_hop->s; + _d->hooks.nh.len = _d->hooks.next_hop->len; + _d->hooks.next_hop = &_d->hooks.nh; + get_raw_uri(_d->hooks.next_hop); + } - return 0; + return 0; } /** @@ -1265,105 +1367,113 @@ static inline int calculate_hooks(dlg_t* _d) * Leaves only the topmost "" Record-Route headers. * */ -int extract_allowed_headers(struct sip_msg *my_msg,int strip_top_vias,int allow_top_Rroutes,hdr_flags_t forbidden_hdrs,char *headers,int headers_len) +int extract_allowed_headers(struct sip_msg *my_msg, int strip_top_vias, + int allow_top_Rroutes, hdr_flags_t forbidden_hdrs, char *headers, + int headers_len) { - struct hdr_field *hf; - rr_t *rb; - struct via_body *vb; - int len,k,rtcnt,i; - - len=0; - rtcnt=allow_top_Rroutes; - rb=NULL; - vb=NULL; - - for(hf=my_msg->headers;hf;hf=hf->next){ - if((hf->type>0) && (forbidden_hdrs & HDR_T2F(hf->type))){ - LM_DBG("Skipping header (%.*s)\n",hf->name.len,hf->name.s); - continue; - }else if(hf->type==HDR_VIA_T && strip_top_vias > 0){ - /** All vias MUST be parsed !!*/ - for(i=0,vb=hf->parsed;vb;vb=vb->next,i++); - if(i<=strip_top_vias){ - LM_DBG("Stripping vias [%.*s]\n",hf->len,hf->name.s); - /** skip this via header*/ - strip_top_vias-=i; - }else{ - assert(i>1); - vb=hf->parsed; - while(strip_top_vias--) - vb=vb->next; - k= (hf->name.s + hf->len) - vb->name.s; - LM_DBG("Stripping vias [%.*s]\n",(int)(vb->name.s-hf->name.s), - hf->name.s); - if(k+VIA_LENname.s,k); - len+=k; - }else{ - LM_ERR("Out Of Space !!\n"); - goto error; - } - } - }else if(hf->type==HDR_RECORDROUTE_T && rtcnt>=0){ - if(rtcnt==0) - continue; - if(!hf->parsed && 0>parse_rr(hf)){ - LM_ERR("parsing Record-Route:\"%.*s\"\n",hf->body.len,hf->body.s); - goto error; - } - for(i=0,rb=hf->parsed;rb;rb=rb->next,i++); - if(i<=rtcnt){ - if((len+hf->len)len,hf->name.s); - memcpy(headers+len,hf->name.s,hf->len); - len+=hf->len; - }else{ - LM_ERR("Unable to keep recordroute (not enough space left in headers) Discarding \"%.*s\" \n",hf->name.len,hf->name.s); - goto error; - } - /** is this dangerous ? because the rtcnt is the control variable for this conditional 'if' + struct hdr_field *hf; + rr_t *rb; + struct via_body *vb; + int len, k, rtcnt, i; + + len = 0; + rtcnt = allow_top_Rroutes; + rb = NULL; + vb = NULL; + + for(hf = my_msg->headers; hf; hf = hf->next) { + if((hf->type > 0) && (forbidden_hdrs & HDR_T2F(hf->type))) { + LM_DBG("Skipping header (%.*s)\n", hf->name.len, hf->name.s); + continue; + } else if(hf->type == HDR_VIA_T && strip_top_vias > 0) { + /** All vias MUST be parsed !!*/ + for(i = 0, vb = hf->parsed; vb; vb = vb->next, i++) + ; + if(i <= strip_top_vias) { + LM_DBG("Stripping vias [%.*s]\n", hf->len, hf->name.s); + /** skip this via header*/ + strip_top_vias -= i; + } else { + assert(i > 1); + vb = hf->parsed; + while(strip_top_vias--) + vb = vb->next; + k = (hf->name.s + hf->len) - vb->name.s; + LM_DBG("Stripping vias [%.*s]\n", + (int)(vb->name.s - hf->name.s), hf->name.s); + if(k + VIA_LEN < headers_len) { + memcpy(headers + len, VIA, VIA_LEN); + len += VIA_LEN; + memcpy(headers + len, vb->name.s, k); + len += k; + } else { + LM_ERR("Out Of Space !!\n"); + goto error; + } + } + } else if(hf->type == HDR_RECORDROUTE_T && rtcnt >= 0) { + if(rtcnt == 0) + continue; + if(!hf->parsed && 0 > parse_rr(hf)) { + LM_ERR("parsing Record-Route:\"%.*s\"\n", hf->body.len, + hf->body.s); + goto error; + } + for(i = 0, rb = hf->parsed; rb; rb = rb->next, i++) + ; + if(i <= rtcnt) { + if((len + hf->len) < headers_len) { + LM_DBG("Allowing RecordRoute [%.*s]\n", hf->len, + hf->name.s); + memcpy(headers + len, hf->name.s, hf->len); + len += hf->len; + } else { + LM_ERR("Unable to keep recordroute (not enough space left " + "in headers) Discarding \"%.*s\" \n", + hf->name.len, hf->name.s); + goto error; + } + /** is this dangerous ? because the rtcnt is the control variable for this conditional 'if' * so if I change rtcnt value in one of the statements... what then ??? */ - rtcnt-=i; - }else{ - assert(rtcnt>0); - rb=hf->parsed; - while(rb && --rtcnt) - rb=rb->next; - if(!rb) { - LM_ERR("no rr\n"); - goto error; + rtcnt -= i; + } else { + assert(rtcnt > 0); + rb = hf->parsed; + while(rb && --rtcnt) + rb = rb->next; + if(!rb) { + LM_ERR("no rr\n"); + goto error; + } + k = (((rb->nameaddr.name.s) + rb->len) - hf->name.s); + if(len + k + CRLF_LEN < headers_len) { + memcpy(headers + len, hf->name.s, k); + LM_DBG("Allowing RecordRoute [%.*s\r\n]\n", k, hf->name.s); + len += k; + memcpy(headers + len, CRLF, CRLF_LEN); + len += CRLF_LEN; + } else { + LM_ERR("Out Of Space !!\n"); + goto error; + } + } + if(hf->parsed) { + free_rr((rr_t **)(void *)(&hf->parsed)); + hf->parsed = NULL; + } + } else { + if((len + hf->len) < headers_len) { + memcpy(headers + len, hf->name.s, hf->len); + len += hf->len; + } else { + LM_WARN("Too many headers. Discarding \"%.*s\" \n", + hf->name.len, hf->name.s); + } } - k= (((rb->nameaddr.name.s) + rb->len)-hf->name.s) ; - if(len+k+CRLF_LENname.s,k); - LM_DBG("Allowing RecordRoute [%.*s\r\n]\n",k,hf->name.s); - len+=k; - memcpy(headers+len,CRLF,CRLF_LEN); - len+=CRLF_LEN; - }else{ - LM_ERR("Out Of Space !!\n"); - goto error; - } - } - if(hf->parsed){ - free_rr((rr_t **)(void*)(&hf->parsed)); - hf->parsed=NULL; - } - }else{ - if((len+hf->len)name.s,hf->len); - len+=hf->len; - }else{ - LM_WARN("Too many headers. Discarding \"%.*s\" \n", - hf->name.len,hf->name.s); - } - } - }/*for*/ - return len; + } /*for*/ + return len; error: - return -1; + return -1; } @@ -1377,88 +1487,89 @@ int extract_allowed_headers(struct sip_msg *my_msg,int strip_top_vias,int allow_ * N: the string * */ -int as_action_fail_resp(int uac_id,int sip_error,char *err_buf,int i) +int as_action_fail_resp(int uac_id, int sip_error, char *err_buf, int i) { - char msg[14+MAX_REASON_LEN]; - int k, ev_len; - k=4; - if(i==0) - i=strlen(err_buf); - if(i>MAX_REASON_LEN){ - LM_ERR("Error Reason bigger than MAX_REASON_LEN\n"); - return -1; - } - msg[k++]=AC_RES_FAIL; - uac_id=htonl(uac_id); - memcpy(msg+k,&uac_id,4); - k+=4; - sip_error=htonl(sip_error); - memcpy(msg+k,&sip_error,4); - k+=4; - msg[k++]=(char)(unsigned char)i; - memcpy(msg+k,err_buf,i); - k+=i; - ev_len=htonl(k); - memcpy(msg,&ev_len,4); - if(write(my_as->u.as.action_fd,msg,k)<=0){ - LM_DBG("Ignoring error write\n"); - } - return 0; + char msg[14 + MAX_REASON_LEN]; + int k, ev_len; + k = 4; + if(i == 0) + i = strlen(err_buf); + if(i > MAX_REASON_LEN) { + LM_ERR("Error Reason bigger than MAX_REASON_LEN\n"); + return -1; + } + msg[k++] = AC_RES_FAIL; + uac_id = htonl(uac_id); + memcpy(msg + k, &uac_id, 4); + k += 4; + sip_error = htonl(sip_error); + memcpy(msg + k, &sip_error, 4); + k += 4; + msg[k++] = (char)(unsigned char)i; + memcpy(msg + k, err_buf, i); + k += i; + ev_len = htonl(k); + memcpy(msg, &ev_len, 4); + if(write(my_as->u.as.action_fd, msg, k) <= 0) { + LM_DBG("Ignoring error write\n"); + } + return 0; } /* * This callback function should be used in order to free the parameters passed to uac_cb. * This callback is called when the transaction is destroyed. */ -void uac_cleanup_cb(struct cell* t, int type, struct tmcb_params *rcvd_params) +void uac_cleanup_cb(struct cell *t, int type, struct tmcb_params *rcvd_params) { struct as_uac_param *ev_info; - ev_info=(struct as_uac_param*)*rcvd_params->param; + ev_info = (struct as_uac_param *)*rcvd_params->param; - if(ev_info) { + if(ev_info) { shm_free(ev_info); - *rcvd_params->param=NULL; + *rcvd_params->param = NULL; } } -void uas_e2e_ack_cb(struct cell* t, int type,struct tmcb_params *rcvd_params) +void uas_e2e_ack_cb(struct cell *t, int type, struct tmcb_params *rcvd_params) { - struct as_uac_param *ev_info; - int mylen; - as_msg_p my_as_ev=NULL; - char *buffer=NULL; + struct as_uac_param *ev_info; + int mylen; + as_msg_p my_as_ev = NULL; + char *buffer = NULL; - ev_info=(struct as_uac_param*)*rcvd_params->param; + ev_info = (struct as_uac_param *)*rcvd_params->param; - if(!(type & TMCB_E2EACK_IN)) - return; + if(!(type & TMCB_E2EACK_IN)) + return; - if(!(my_as_ev=shm_malloc(sizeof(as_msg_t)))){ - LM_ERR("no more shared mem\n"); - goto error; - } - if(!(buffer=create_as_event_t(t,rcvd_params->req,ev_info->processor_id,&mylen,E2E_ACK))){ - LM_ERR("unable to create event code\n"); - goto error; - } - my_as_ev->as = ev_info->who; - my_as_ev->msg = buffer; - my_as_ev->len = mylen; - my_as_ev->type = RES_IN; - my_as_ev->transaction = t; - if(write(write_pipe,&my_as_ev,sizeof(as_msg_p))<=0){ - goto error; - } - goto exit; + if(!(my_as_ev = shm_malloc(sizeof(as_msg_t)))) { + LM_ERR("no more shared mem\n"); + goto error; + } + if(!(buffer = create_as_event_t(t, rcvd_params->req, ev_info->processor_id, + &mylen, E2E_ACK))) { + LM_ERR("unable to create event code\n"); + goto error; + } + my_as_ev->as = ev_info->who; + my_as_ev->msg = buffer; + my_as_ev->len = mylen; + my_as_ev->type = RES_IN; + my_as_ev->transaction = t; + if(write(write_pipe, &my_as_ev, sizeof(as_msg_p)) <= 0) { + goto error; + } + goto exit; error: - if(my_as_ev){ - shm_free(my_as_ev); - } - if(buffer) - shm_free(buffer); + if(my_as_ev) { + shm_free(my_as_ev); + } + if(buffer) + shm_free(buffer); exit: - return ; + return; } /** @@ -1467,156 +1578,158 @@ void uas_e2e_ack_cb(struct cell* t, int type,struct tmcb_params *rcvd_params) * fifo (not to the ActionDispatcher) so EventDispatcher will be the one who * will send the event to the AppServer. */ -void uac_cb(struct cell* t, int type,struct tmcb_params *rcvd_params) +void uac_cb(struct cell *t, int type, struct tmcb_params *rcvd_params) { - as_msg_p my_as_ev=0; - int mylen,code,i; - struct as_uac_param *ev_info; - char *buffer; - - ev_info=(struct as_uac_param*)*rcvd_params->param; - code=rcvd_params->code; - buffer=0; - if(!ev_info || !ev_info->who){ - return; - } + as_msg_p my_as_ev = 0; + int mylen, code, i; + struct as_uac_param *ev_info; + char *buffer; - if(type == TMCB_LOCAL_COMPLETED && !ev_info->destroy_cb_set) { - if(seas_f.tmb.register_tmcb(NULL, t, TMCB_DESTROY , uac_cleanup_cb, (void*)ev_info, 0) <= 0) { - LM_ERR( "register_tmcb for destroy callback failed\n"); - goto error; - } - ev_info->destroy_cb_set = 1; - } + ev_info = (struct as_uac_param *)*rcvd_params->param; + code = rcvd_params->code; + buffer = 0; + if(!ev_info || !ev_info->who) { + return; + } - LM_DBG("reply to UAC Transaction for AS:%.*s code: %d\n", - ev_info->who->name.len,ev_info->who->name.s,code); - LM_DBG("transaction %p Nr_of_outgoings:%d is_Local:%c\n", - t,t->nr_of_outgoings,is_local(t)?'y':'n'); - for(i=0;inr_of_outgoings;i++) - LM_DBG("UAC[%d].last_received=%d\n",i,t->uac[i].last_received); - if(!(my_as_ev=shm_malloc(sizeof(as_msg_t)))){ - LM_ERR("no more shared mem\n"); - goto error; - } - if(!(buffer=create_as_action_reply(t,rcvd_params,ev_info->uac_id,ev_info->processor_id,&mylen))){ - LM_ERR("failed to encode message\n"); - goto error; - } - my_as_ev->as = ev_info->who; - my_as_ev->msg = buffer; - my_as_ev->len = mylen; - my_as_ev->type = RES_IN; - my_as_ev->transaction = t; - if(write(write_pipe,&my_as_ev,sizeof(as_msg_p))<=0){ - goto error; - } - goto exit; + if(type == TMCB_LOCAL_COMPLETED && !ev_info->destroy_cb_set) { + if(seas_f.tmb.register_tmcb( + NULL, t, TMCB_DESTROY, uac_cleanup_cb, (void *)ev_info, 0) + <= 0) { + LM_ERR("register_tmcb for destroy callback failed\n"); + goto error; + } + ev_info->destroy_cb_set = 1; + } + + LM_DBG("reply to UAC Transaction for AS:%.*s code: %d\n", + ev_info->who->name.len, ev_info->who->name.s, code); + LM_DBG("transaction %p Nr_of_outgoings:%d is_Local:%c\n", t, + t->nr_of_outgoings, is_local(t) ? 'y' : 'n'); + for(i = 0; i < t->nr_of_outgoings; i++) + LM_DBG("UAC[%d].last_received=%d\n", i, t->uac[i].last_received); + if(!(my_as_ev = shm_malloc(sizeof(as_msg_t)))) { + LM_ERR("no more shared mem\n"); + goto error; + } + if(!(buffer = create_as_action_reply(t, rcvd_params, ev_info->uac_id, + ev_info->processor_id, &mylen))) { + LM_ERR("failed to encode message\n"); + goto error; + } + my_as_ev->as = ev_info->who; + my_as_ev->msg = buffer; + my_as_ev->len = mylen; + my_as_ev->type = RES_IN; + my_as_ev->transaction = t; + if(write(write_pipe, &my_as_ev, sizeof(as_msg_p)) <= 0) { + goto error; + } + goto exit; error: - if(my_as_ev){ - shm_free(my_as_ev); - } - if(buffer) - shm_free(buffer); + if(my_as_ev) { + shm_free(my_as_ev); + } + if(buffer) + shm_free(buffer); exit: - return ; + return; } -char* create_as_action_reply(struct cell *c,struct tmcb_params *params,int uac_id,char processor_id,int *evt_len) +char *create_as_action_reply(struct cell *c, struct tmcb_params *params, + int uac_id, char processor_id, int *evt_len) { - int i; - unsigned int code,flags; - unsigned short int port; - unsigned int k,len; - char *buffer; - struct sip_msg *msg; - if(!(buffer=shm_malloc(ENCODED_MSG_SIZE))){ - LM_ERR("create_as_action_reply Out Of Memory !!\n"); - return 0; - } - msg=0; - *evt_len=0; - flags=0; - if(params->rpl==FAKED_REPLY) - flags=FAKED_REPLY_FLAG; - /*length*/ - k=4; - /*type*/ - buffer[k++]=(unsigned char)RES_IN; - /*processor id*/ - buffer[k++]=processor_id; - /*flags (by now, not used)*/ - flags=htonl(flags); - memcpy(buffer+k,&flags,4); - k+=4; - /*recv info*/ - if(!(params->rpl == FAKED_REPLY)) { - msg=params->rpl; - /*protocol should be UDP,TCP,TLS or whatever*/ - buffer[k++]=(unsigned char)msg->rcv.proto; - /*src ip len + src ip*/ - len=msg->rcv.src_ip.len; - buffer[k++]=(unsigned char)len; - memcpy(buffer+k,&(msg->rcv.src_ip.u),len); - k+=len; - /*dst ip len + dst ip*/ - len=msg->rcv.dst_ip.len; - buffer[k++]=(unsigned char)len; - memcpy(buffer+k,&(msg->rcv.dst_ip.u),len); - k+=len; - /*src port */ - port=htons(msg->rcv.src_port); - memcpy(buffer+k,&port,2); - k+=2; - /*dst port */ - port=htons(msg->rcv.dst_port); - memcpy(buffer+k,&port,2); - k+=2; - }else{ - /*protocol*/ - buffer[k++]=0; - /*src ip len*/ - buffer[k++]=0; - /*dst ip len*/ - buffer[k++]=0; - /*skip src port and dst port*/ - buffer[k++]=0; - buffer[k++]=0; - buffer[k++]=0; - buffer[k++]=0; - } - /*hash_index*/ - i=htonl(c->hash_index); - memcpy(buffer+k,&i,4); - k+=4; - /*label*/ - i=(!strncmp(c->method.s,"CANCEL",6)) ? \ - htonl(((struct as_uac_param*)*params->param)->label) : \ - htonl(c->label); - memcpy(buffer+k,&i,4); - k+=4; - /*uac_id*/ - uac_id=htonl(uac_id); - memcpy(buffer+k,&uac_id,4); - k+=4; - /*code*/ - code=htonl(params->code); - memcpy(buffer+k,&code,4); - k+=4; - /*length of event (hdr+payload-4), copied at the beginning*/ - if(params->rpl != FAKED_REPLY) { - if((i=encode_msg(msg,buffer+k,ENCODED_MSG_SIZE-k))<0){ - LM_ERR("failed to encode msg\n"); - goto error; - } - k+=i; - } - *evt_len=k; - k=htonl(k); - memcpy(buffer,&k,4); - return buffer; + int i; + unsigned int code, flags; + unsigned short int port; + unsigned int k, len; + char *buffer; + struct sip_msg *msg; + if(!(buffer = shm_malloc(ENCODED_MSG_SIZE))) { + LM_ERR("create_as_action_reply Out Of Memory !!\n"); + return 0; + } + msg = 0; + *evt_len = 0; + flags = 0; + if(params->rpl == FAKED_REPLY) + flags = FAKED_REPLY_FLAG; + /*length*/ + k = 4; + /*type*/ + buffer[k++] = (unsigned char)RES_IN; + /*processor id*/ + buffer[k++] = processor_id; + /*flags (by now, not used)*/ + flags = htonl(flags); + memcpy(buffer + k, &flags, 4); + k += 4; + /*recv info*/ + if(!(params->rpl == FAKED_REPLY)) { + msg = params->rpl; + /*protocol should be UDP,TCP,TLS or whatever*/ + buffer[k++] = (unsigned char)msg->rcv.proto; + /*src ip len + src ip*/ + len = msg->rcv.src_ip.len; + buffer[k++] = (unsigned char)len; + memcpy(buffer + k, &(msg->rcv.src_ip.u), len); + k += len; + /*dst ip len + dst ip*/ + len = msg->rcv.dst_ip.len; + buffer[k++] = (unsigned char)len; + memcpy(buffer + k, &(msg->rcv.dst_ip.u), len); + k += len; + /*src port */ + port = htons(msg->rcv.src_port); + memcpy(buffer + k, &port, 2); + k += 2; + /*dst port */ + port = htons(msg->rcv.dst_port); + memcpy(buffer + k, &port, 2); + k += 2; + } else { + /*protocol*/ + buffer[k++] = 0; + /*src ip len*/ + buffer[k++] = 0; + /*dst ip len*/ + buffer[k++] = 0; + /*skip src port and dst port*/ + buffer[k++] = 0; + buffer[k++] = 0; + buffer[k++] = 0; + buffer[k++] = 0; + } + /*hash_index*/ + i = htonl(c->hash_index); + memcpy(buffer + k, &i, 4); + k += 4; + /*label*/ + i = (!strncmp(c->method.s, "CANCEL", 6)) + ? htonl(((struct as_uac_param *)*params->param)->label) + : htonl(c->label); + memcpy(buffer + k, &i, 4); + k += 4; + /*uac_id*/ + uac_id = htonl(uac_id); + memcpy(buffer + k, &uac_id, 4); + k += 4; + /*code*/ + code = htonl(params->code); + memcpy(buffer + k, &code, 4); + k += 4; + /*length of event (hdr+payload-4), copied at the beginning*/ + if(params->rpl != FAKED_REPLY) { + if((i = encode_msg(msg, buffer + k, ENCODED_MSG_SIZE - k)) < 0) { + LM_ERR("failed to encode msg\n"); + goto error; + } + k += i; + } + *evt_len = k; + k = htonl(k); + memcpy(buffer, &k, 4); + return buffer; error: - return 0; + return 0; } - - diff --git a/src/modules/seas/seas_action.h b/src/modules/seas/seas_action.h index b9b6a3399ee..9f24a039d2a 100644 --- a/src/modules/seas/seas_action.h +++ b/src/modules/seas/seas_action.h @@ -20,14 +20,14 @@ */ -#include "seas.h"/*as_p*/ +#include "seas.h" /*as_p*/ #define REPLY_PROV 1 -#define REPLY_FIN 2 -#define REPLY_FIN_DLG 3 -#define UAC_REQ 4 +#define REPLY_FIN 2 +#define REPLY_FIN_DLG 3 +#define UAC_REQ 4 #define AC_RES_FAIL 5 -#define SL_MSG 6 +#define SL_MSG 6 #define AC_CANCEL 7 #define JAIN_PONG 8 @@ -36,30 +36,38 @@ #define FAKED_REPLY_FLAG 0x02 -struct as_uac_param{ - struct as_entry *who; - int uac_id; - unsigned int label; - char processor_id; - char destroy_cb_set; - struct cell* inviteT; +struct as_uac_param +{ + struct as_entry *who; + int uac_id; + unsigned int label; + char processor_id; + char destroy_cb_set; + struct cell *inviteT; }; /** * ACTION processing functions */ -int ac_reply(as_p the_as,unsigned char processor_id,unsigned int flags,char *action,int len); -int ac_sl_msg(as_p the_as,unsigned char processor_id,unsigned int flags,char *action,int len); -int ac_uac_req(as_p the_as,unsigned char processor_id,unsigned int flags,char *action,int len); -int ac_encode_msg(as_p the_as,unsigned char processor_id,unsigned int flags,char *action,int len); -int ac_cancel(as_p the_as,unsigned char processor_id,unsigned int flags,char *action,int len); +int ac_reply(as_p the_as, unsigned char processor_id, unsigned int flags, + char *action, int len); +int ac_sl_msg(as_p the_as, unsigned char processor_id, unsigned int flags, + char *action, int len); +int ac_uac_req(as_p the_as, unsigned char processor_id, unsigned int flags, + char *action, int len); +int ac_encode_msg(as_p the_as, unsigned char processor_id, unsigned int flags, + char *action, int len); +int ac_cancel(as_p the_as, unsigned char processor_id, unsigned int flags, + char *action, int len); /** * Utility functions */ -int forward_sl_request(struct sip_msg *msg,str *uri,int proto); -int extract_allowed_headers(struct sip_msg *my_msg,int allow_vias,int allow_Rroutes,hdr_flags_t forbidden_hdrs,char *headers,int headers_len); +int forward_sl_request(struct sip_msg *msg, str *uri, int proto); +int extract_allowed_headers(struct sip_msg *my_msg, int allow_vias, + int allow_Rroutes, hdr_flags_t forbidden_hdrs, char *headers, + int headers_len); /** * Action Dispatcher process functions @@ -70,11 +78,12 @@ int process_action(as_p my_as); /** * Callback Functions */ -void uac_cb(struct cell* t, int type, struct tmcb_params*); -void uac_cleanup_cb(struct cell* t, int type, struct tmcb_params*); +void uac_cb(struct cell *t, int type, struct tmcb_params *); +void uac_cleanup_cb(struct cell *t, int type, struct tmcb_params *); /** * Event creating functions */ -int as_action_fail_resp(int uac_id,int sip_error,char *err_buf,int err_len); -char* create_as_action_reply(struct cell *c,struct tmcb_params *params,int uac_id,char processor_id,int *evt_len); +int as_action_fail_resp(int uac_id, int sip_error, char *err_buf, int err_len); +char *create_as_action_reply(struct cell *c, struct tmcb_params *params, + int uac_id, char processor_id, int *evt_len); diff --git a/src/modules/seas/seas_error.h b/src/modules/seas/seas_error.h index f54c795f0bd..ce33bd65920 100644 --- a/src/modules/seas/seas_error.h +++ b/src/modules/seas/seas_error.h @@ -26,9 +26,9 @@ /** Kamailio ERRORS ARE NEGATIVE, SEAS ERROR CODES ARE POSITIVE */ #define SE_CANCEL_MSG "500 SEAS cancel error" -#define SE_CANCEL_MSG_LEN (sizeof(SE_CANCEL_MSG)-1) +#define SE_CANCEL_MSG_LEN (sizeof(SE_CANCEL_MSG) - 1) #define SE_CANCEL 1 #define SE_UAC_MSG "500 SEAS uac error" -#define SE_UAC_MSG_LEN (sizeof(SE_UAC_MSG)-1) +#define SE_UAC_MSG_LEN (sizeof(SE_UAC_MSG) - 1) #define SE_UAC 2 diff --git a/src/modules/seas/statistics.c b/src/modules/seas/statistics.c index 2e1006a381d..33379ff6786 100644 --- a/src/modules/seas/statistics.c +++ b/src/modules/seas/statistics.c @@ -42,51 +42,53 @@ #include "../../core/locking.h" #define STATS_PAY 101 -struct statstable* seas_stats_table; +struct statstable *seas_stats_table; int stats_fd; -char use_stats=0; +char use_stats = 0; pid_t pid; static void sig_handler(int signo) { - switch(signo){ - case SIGTERM: - LM_ERR("stats process caught SIGTERM, shutting down..\n"); - close(stats_fd); - destroy_seas_stats_table(); - exit(0); - default: - LM_DBG("caught signal %d\n",signo); - } - LM_WARN("statistics process:caught signal (%d)\n",signo); + switch(signo) { + case SIGTERM: + LM_ERR("stats process caught SIGTERM, shutting down..\n"); + close(stats_fd); + destroy_seas_stats_table(); + exit(0); + default: + LM_DBG("caught signal %d\n", signo); + } + LM_WARN("statistics process:caught signal (%d)\n", signo); } -struct statstable* init_seas_stats_table(void) +struct statstable *init_seas_stats_table(void) { - /*allocs the table*/ - seas_stats_table= (struct statstable*)shm_malloc( sizeof( struct statstable ) ); - if (!seas_stats_table) { - LM_ERR("no shmem for stats table (%d bytes)\n",(int)sizeof(struct statstable)); - return 0; - } - memset(seas_stats_table, 0, sizeof(struct statstable) ); - if(0==(seas_stats_table->mutex=lock_alloc())){ - LM_ERR("couldn't alloc mutex (get_lock_t)\n"); - shm_free(seas_stats_table); - return 0; - } - lock_init(seas_stats_table->mutex); - return seas_stats_table; + /*allocs the table*/ + seas_stats_table = + (struct statstable *)shm_malloc(sizeof(struct statstable)); + if(!seas_stats_table) { + LM_ERR("no shmem for stats table (%d bytes)\n", + (int)sizeof(struct statstable)); + return 0; + } + memset(seas_stats_table, 0, sizeof(struct statstable)); + if(0 == (seas_stats_table->mutex = lock_alloc())) { + LM_ERR("couldn't alloc mutex (get_lock_t)\n"); + shm_free(seas_stats_table); + return 0; + } + lock_init(seas_stats_table->mutex); + return seas_stats_table; } void destroy_seas_stats_table(void) { - /*deallocs the table*/ - if(seas_stats_table){ - lock_destroy(seas_stats_table->mutex); - shm_free(seas_stats_table); - seas_stats_table=(struct statstable *)0; - } + /*deallocs the table*/ + if(seas_stats_table) { + lock_destroy(seas_stats_table->mutex); + shm_free(seas_stats_table); + seas_stats_table = (struct statstable *)0; + } } /** This will be called from within w_as_relay() @@ -95,33 +97,33 @@ void destroy_seas_stats_table(void) */ void as_relay_stat(struct cell *t) { - struct statscell *s; - struct totag_elem *to; - if(t==0) - return; - if(t->fwded_totags != 0){ - LM_DBG("seas:as_relay_stat() unable to put a payload " - "in fwded_totags because it is being used !!\n"); - return; - } - if(!(s=shm_malloc(sizeof(struct statscell)))){ - return; - } - if(!(to=shm_malloc(sizeof(struct totag_elem)))){ - shm_free(s); - return; - } - memset(s,0,sizeof(struct statscell)); - gettimeofday(&(s->u.uas.as_relay),NULL); - s->type=UAS_T; - to->tag.len=0; - to->tag.s=(char *)s; - to->next=0; - to->acked=STATS_PAY; - t->fwded_totags=to; - lock_get(seas_stats_table->mutex); - (seas_stats_table->started_transactions)++; - lock_release(seas_stats_table->mutex); + struct statscell *s; + struct totag_elem *to; + if(t == 0) + return; + if(t->fwded_totags != 0) { + LM_DBG("seas:as_relay_stat() unable to put a payload " + "in fwded_totags because it is being used !!\n"); + return; + } + if(!(s = shm_malloc(sizeof(struct statscell)))) { + return; + } + if(!(to = shm_malloc(sizeof(struct totag_elem)))) { + shm_free(s); + return; + } + memset(s, 0, sizeof(struct statscell)); + gettimeofday(&(s->u.uas.as_relay), NULL); + s->type = UAS_T; + to->tag.len = 0; + to->tag.s = (char *)s; + to->next = 0; + to->acked = STATS_PAY; + t->fwded_totags = to; + lock_get(seas_stats_table->mutex); + (seas_stats_table->started_transactions)++; + lock_release(seas_stats_table->mutex); } /** this will be called from the SEAS event dispatcher @@ -133,35 +135,35 @@ void as_relay_stat(struct cell *t) */ void event_stat(struct cell *t) { - struct statscell *s; - struct totag_elem *to; - if(t==0){ - /*seas_f.tmb.t_lookup_ident(&t,hash_index,label); BAD bcos it refcounts, + struct statscell *s; + struct totag_elem *to; + if(t == 0) { + /*seas_f.tmb.t_lookup_ident(&t,hash_index,label); BAD bcos it refcounts, * and there's no way to simply unrefcount from outside TM*/ - return; - } - if(t->fwded_totags == 0){ - LM_DBG("seas:event_stat() unabe to set the event_stat timeval:" - " no payload found at cell!! (fwded_totags=0)\n"); - return; - } - /*esto da un CORE DUMP cuando hay mucha carga.. warning*/ - to=t->fwded_totags; - while(to){ - if(to->acked==STATS_PAY){ - s=(struct statscell *)to->tag.s; - gettimeofday(&(s->u.uas.event_sent),NULL); - return; - }else - to=to->next; - } - return; + return; + } + if(t->fwded_totags == 0) { + LM_DBG("seas:event_stat() unabe to set the event_stat timeval:" + " no payload found at cell!! (fwded_totags=0)\n"); + return; + } + /*esto da un CORE DUMP cuando hay mucha carga.. warning*/ + to = t->fwded_totags; + while(to) { + if(to->acked == STATS_PAY) { + s = (struct statscell *)to->tag.s; + gettimeofday(&(s->u.uas.event_sent), NULL); + return; + } else + to = to->next; + } + return; } /** param i is in milliseconds*/ static inline int assignIndex(int i) { - return (i/100)>14?14:(i/100); + return (i / 100) > 14 ? 14 : (i / 100); } /** this will be called from the SEAS action dispatcher @@ -169,44 +171,45 @@ static inline int assignIndex(int i) */ void action_stat(struct cell *t) { - unsigned int seas_dispatch; - //unsigned int as_delay; - struct timeval *t1,*t2; - //struct timeval *t3; - struct statscell *s; - struct totag_elem *to; - if(t==0) - return; - if(t->fwded_totags == 0){ - LM_DBG("seas:event_stat() unable to set the event_stat timeval:" - " no payload found at cell!! (fwded_totags=0)\n"); - return; - } - to=t->fwded_totags; - while(to){ - if(to->acked==STATS_PAY){ - s=(struct statscell *)to->tag.s; - gettimeofday(&(s->u.uas.action_recvd),NULL); - break; - }else - to=to->next; - } - /**no statistics found**/ - if(to==0) - return; - t1=&(s->u.uas.as_relay); - t2=&(s->u.uas.event_sent); - //t3=&(s->u.uas.action_recvd); - seas_dispatch = (t2->tv_sec - t1->tv_sec)*1000 + (t2->tv_usec-t1->tv_usec)/1000; - //as_delay = (t3->tv_sec - t2->tv_sec)*1000 + (t3->tv_usec-t2->tv_usec)/1000; + unsigned int seas_dispatch; + //unsigned int as_delay; + struct timeval *t1, *t2; + //struct timeval *t3; + struct statscell *s; + struct totag_elem *to; + if(t == 0) + return; + if(t->fwded_totags == 0) { + LM_DBG("seas:event_stat() unable to set the event_stat timeval:" + " no payload found at cell!! (fwded_totags=0)\n"); + return; + } + to = t->fwded_totags; + while(to) { + if(to->acked == STATS_PAY) { + s = (struct statscell *)to->tag.s; + gettimeofday(&(s->u.uas.action_recvd), NULL); + break; + } else + to = to->next; + } + /**no statistics found**/ + if(to == 0) + return; + t1 = &(s->u.uas.as_relay); + t2 = &(s->u.uas.event_sent); + //t3=&(s->u.uas.action_recvd); + seas_dispatch = (t2->tv_sec - t1->tv_sec) * 1000 + + (t2->tv_usec - t1->tv_usec) / 1000; + //as_delay = (t3->tv_sec - t2->tv_sec)*1000 + (t3->tv_usec-t2->tv_usec)/1000; - lock_get(seas_stats_table->mutex); - { - seas_stats_table->dispatch[assignIndex(seas_dispatch)]++; - seas_stats_table->event[assignIndex(seas_dispatch)]++; - (seas_stats_table->finished_transactions)++; - } - lock_release(seas_stats_table->mutex); + lock_get(seas_stats_table->mutex); + { + seas_stats_table->dispatch[assignIndex(seas_dispatch)]++; + seas_stats_table->event[assignIndex(seas_dispatch)]++; + (seas_stats_table->finished_transactions)++; + } + lock_release(seas_stats_table->mutex); } @@ -221,79 +224,82 @@ void action_stat(struct cell *t) */ int start_stats_server(char *stats_socket) { - char *p,*port; - unsigned short stats_port; - struct hostent *he; - /*use sockaddr_storage ??*/ - struct sockaddr_in su; - int optval; + char *p, *port; + unsigned short stats_port; + struct hostent *he; + /*use sockaddr_storage ??*/ + struct sockaddr_in su; + int optval; - use_stats=0; - port=(char *)0; - he=(struct hostent *)0; - stats_fd=-1; - p=stats_socket; + use_stats = 0; + port = (char *)0; + he = (struct hostent *)0; + stats_fd = -1; + p = stats_socket; - if(p==0 || *p==0) - return 0; + if(p == 0 || *p == 0) + return 0; - if(!init_seas_stats_table()){ - LM_ERR("unable to init stats table, disabling statistics\n"); - return -1; - } - while(*p){ - if(*p == ':'){ - *p=0; - port=p+1; - break; - } - } - if(!(he=resolvehost(stats_socket))) - goto error; - if(port==(char*)0 || *port==0) - stats_port=5088; - else if(!(stats_port=str2s(port,strlen(port),0))){ - LM_ERR("invalid port %s\n",port); - goto error; - } - if((stats_fd=socket(he->h_addrtype, SOCK_STREAM, 0))==-1){ - LM_ERR("trying to open server socket (%s)\n",strerror(errno)); - goto error; - } - optval=1; - if (setsockopt(stats_fd, SOL_SOCKET, SO_REUSEADDR, (void*)&optval, sizeof(optval))==-1) { - LM_ERR("setsockopt (%s)\n",strerror(errno)); - goto error; - } - su.sin_family = he->h_addrtype; - su.sin_port=htons(stats_port); - memcpy(&su.sin_addr,he->h_addr_list[0],4); - if((bind(stats_fd,(struct sockaddr*)&su,sizeof(struct sockaddr_in)))==-1){ - LM_ERR( "bind (%s)\n",strerror(errno)); - goto error; - } - if(listen(stats_fd, 10)==-1){ - LM_ERR( "listen (%s)\n",strerror(errno)); - goto error; - } - if(!(pid=fork())){/*child*/ - signal(SIGTERM,sig_handler); - serve_stats(stats_fd); - printf("statistics Server Process exits !!\n"); - exit(0); - }else if(pid>0){/*parent*/ - close(stats_fd); - }else{/*error*/ - LM_ERR("failed to create stats server process\n"); - goto error; - } - use_stats=1; - return 1; + if(!init_seas_stats_table()) { + LM_ERR("unable to init stats table, disabling statistics\n"); + return -1; + } + while(*p) { + if(*p == ':') { + *p = 0; + port = p + 1; + break; + } + } + if(!(he = resolvehost(stats_socket))) + goto error; + if(port == (char *)0 || *port == 0) + stats_port = 5088; + else if(!(stats_port = str2s(port, strlen(port), 0))) { + LM_ERR("invalid port %s\n", port); + goto error; + } + if((stats_fd = socket(he->h_addrtype, SOCK_STREAM, 0)) == -1) { + LM_ERR("trying to open server socket (%s)\n", strerror(errno)); + goto error; + } + optval = 1; + if(setsockopt(stats_fd, SOL_SOCKET, SO_REUSEADDR, (void *)&optval, + sizeof(optval)) + == -1) { + LM_ERR("setsockopt (%s)\n", strerror(errno)); + goto error; + } + su.sin_family = he->h_addrtype; + su.sin_port = htons(stats_port); + memcpy(&su.sin_addr, he->h_addr_list[0], 4); + if((bind(stats_fd, (struct sockaddr *)&su, sizeof(struct sockaddr_in))) + == -1) { + LM_ERR("bind (%s)\n", strerror(errno)); + goto error; + } + if(listen(stats_fd, 10) == -1) { + LM_ERR("listen (%s)\n", strerror(errno)); + goto error; + } + if(!(pid = fork())) { /*child*/ + signal(SIGTERM, sig_handler); + serve_stats(stats_fd); + printf("statistics Server Process exits !!\n"); + exit(0); + } else if(pid > 0) { /*parent*/ + close(stats_fd); + } else { /*error*/ + LM_ERR("failed to create stats server process\n"); + goto error; + } + use_stats = 1; + return 1; error: - if(stats_fd!=-1) - close(stats_fd); - destroy_seas_stats_table(); - return -1; + if(stats_fd != -1) + close(stats_fd); + destroy_seas_stats_table(); + return -1; } /** @@ -307,61 +313,61 @@ int start_stats_server(char *stats_socket) */ int stop_stats_server(void) { - if(pid) - kill(SIGTERM,pid); - return 0; + if(pid) + kill(SIGTERM, pid); + return 0; } void serve_stats(int fd) { - union sockaddr_union su; - int sock,i,retrn; - socklen_t su_len; - char f; - /* we install our signal handler..*/ - signal(SIGTERM,sig_handler); - signal(SIGHUP,sig_handler); - signal(SIGPIPE,sig_handler); - signal(SIGQUIT,sig_handler); - signal(SIGINT,sig_handler); - signal(SIGCHLD,sig_handler); + union sockaddr_union su; + int sock, i, retrn; + socklen_t su_len; + char f; + /* we install our signal handler..*/ + signal(SIGTERM, sig_handler); + signal(SIGHUP, sig_handler); + signal(SIGPIPE, sig_handler); + signal(SIGQUIT, sig_handler); + signal(SIGINT, sig_handler); + signal(SIGCHLD, sig_handler); - while(1){ - su_len = sizeof(union sockaddr_union); - sock=-1; - sock=accept(fd, &su.s, &su_len); - if(sock==-1){ - if(errno==EINTR){ - continue; - }else{ - LM_ERR("failed to accept connection: %s\n", strerror(errno)); - return ; - } - } - while(0!=(i=read(sock,&f,1))){ - if(i==-1){ - if(errno==EINTR){ - continue; - }else{ - LM_ERR("unknown error reading from socket\n"); - close(sock); - /** and continue accept()'ing*/ - break; - } - } - retrn=print_stats_info(f,sock); - if(retrn==-1){ - /**simple error happened, don't worry*/ - LM_ERR("printing statisticss \n"); - continue; - }else if(retrn==-2){ - /**let's go to the outer loop, and receive more Statistics clients*/ - LM_ERR("statistics client left\n"); - close(sock); - break; - } - } - } + while(1) { + su_len = sizeof(union sockaddr_union); + sock = -1; + sock = accept(fd, &su.s, &su_len); + if(sock == -1) { + if(errno == EINTR) { + continue; + } else { + LM_ERR("failed to accept connection: %s\n", strerror(errno)); + return; + } + } + while(0 != (i = read(sock, &f, 1))) { + if(i == -1) { + if(errno == EINTR) { + continue; + } else { + LM_ERR("unknown error reading from socket\n"); + close(sock); + /** and continue accept()'ing*/ + break; + } + } + retrn = print_stats_info(f, sock); + if(retrn == -1) { + /**simple error happened, don't worry*/ + LM_ERR("printing statisticss \n"); + continue; + } else if(retrn == -2) { + /**let's go to the outer loop, and receive more Statistics clients*/ + LM_ERR("statistics client left\n"); + close(sock); + break; + } + } + } } /** @@ -370,83 +376,109 @@ void serve_stats(int fd) * this limit then the return value is the number of characters (not including the trailing '\\0') which would have been written to the final string * if enough space had been available. Thus, a return value of size or more means that the output was truncated." */ -int print_stats_info(int f,int sock) +int print_stats_info(int f, int sock) { -#define STATS_BUF_SIZE 400 - int j,k,writen; - char buf[STATS_BUF_SIZE]; +#define STATS_BUF_SIZE 400 + int j, k, writen; + char buf[STATS_BUF_SIZE]; - writen=0; - if(0>(k=snprintf(buf,STATS_BUF_SIZE, "Timings: 0-1 1-2 2-3 3-4 4-5 5-6 6-7 7-8 8-9 9-10 10-11 11-12 12-13 13-14 14+\n"))){ - goto error; - }else{ - if(k>STATS_BUF_SIZE){ - j=STATS_BUF_SIZE; - goto send; - } - j=k; - } - lock_get(seas_stats_table->mutex); - if(0>(k=snprintf(&buf[j],STATS_BUF_SIZE-j,"UAS:dispatch: %-5d %-5d %-5d %-5d %-5d %-5d %-5d %-5d %-5d %-5d %-5d %-5d %-5d %-5d %-5d\n",\ - seas_stats_table->dispatch[0],seas_stats_table->dispatch[1],seas_stats_table->dispatch[2],seas_stats_table->dispatch[3],seas_stats_table->dispatch[4]\ - ,seas_stats_table->dispatch[5],seas_stats_table->dispatch[6],seas_stats_table->dispatch[7],seas_stats_table->dispatch[8],seas_stats_table->dispatch[9],\ - seas_stats_table->dispatch[10],seas_stats_table->dispatch[11],seas_stats_table->dispatch[12],seas_stats_table->dispatch[13],seas_stats_table->dispatch[14]))){ - goto error; - }else{ - if(k>(STATS_BUF_SIZE-j)){ - j=STATS_BUF_SIZE; - goto send; - } - j+=k; - } - if(0>(k=snprintf(&buf[j],STATS_BUF_SIZE-j,"UAS:event: %-5d %-5d %-5d %-5d %-5d %-5d %-5d %-5d %-5d %-5d %-5d %-5d %-5d %-5d %-5d\n",\ - seas_stats_table->event[0],seas_stats_table->event[1],seas_stats_table->event[2],seas_stats_table->event[3],seas_stats_table->event[4]\ - ,seas_stats_table->event[5],seas_stats_table->event[6],seas_stats_table->event[7],seas_stats_table->event[8],seas_stats_table->event[9],\ - seas_stats_table->event[10],seas_stats_table->event[11],seas_stats_table->event[12],seas_stats_table->event[13],seas_stats_table->event[14]))){ - goto error; - }else{ - if(k>STATS_BUF_SIZE-j){ - j=STATS_BUF_SIZE; - goto send; - } - j+=k; - } - if(0>(k=snprintf(&buf[j],STATS_BUF_SIZE-j,"Started Transactions: %d\nTerminated Transactions:%d\nReceived replies:%d\nReceived:%d\n",\ - seas_stats_table->started_transactions,seas_stats_table->finished_transactions,seas_stats_table->received_replies,seas_stats_table->received))){ - goto error; - }else{ - if(k>STATS_BUF_SIZE-j){ - j=STATS_BUF_SIZE; - goto send; - } - j+=k; - } + writen = 0; + if(0 > (k = snprintf(buf, STATS_BUF_SIZE, + "Timings: 0-1 1-2 2-3 3-4 4-5 5-6 6-7 " + "7-8 8-9 9-10 10-11 11-12 12-13 13-14 14+\n"))) { + goto error; + } else { + if(k > STATS_BUF_SIZE) { + j = STATS_BUF_SIZE; + goto send; + } + j = k; + } + lock_get(seas_stats_table->mutex); + if(0 > (k = snprintf(&buf[j], STATS_BUF_SIZE - j, + "UAS:dispatch: %-5d %-5d %-5d %-5d %-5d %-5d %-5d %-5d " + "%-5d %-5d %-5d %-5d %-5d %-5d %-5d\n", + seas_stats_table->dispatch[0], + seas_stats_table->dispatch[1], + seas_stats_table->dispatch[2], + seas_stats_table->dispatch[3], + seas_stats_table->dispatch[4], + seas_stats_table->dispatch[5], + seas_stats_table->dispatch[6], + seas_stats_table->dispatch[7], + seas_stats_table->dispatch[8], + seas_stats_table->dispatch[9], + seas_stats_table->dispatch[10], + seas_stats_table->dispatch[11], + seas_stats_table->dispatch[12], + seas_stats_table->dispatch[13], + seas_stats_table->dispatch[14]))) { + goto error; + } else { + if(k > (STATS_BUF_SIZE - j)) { + j = STATS_BUF_SIZE; + goto send; + } + j += k; + } + if(0 > (k = snprintf(&buf[j], STATS_BUF_SIZE - j, + "UAS:event: %-5d %-5d %-5d %-5d %-5d %-5d %-5d %-5d " + "%-5d %-5d %-5d %-5d %-5d %-5d %-5d\n", + seas_stats_table->event[0], seas_stats_table->event[1], + seas_stats_table->event[2], seas_stats_table->event[3], + seas_stats_table->event[4], seas_stats_table->event[5], + seas_stats_table->event[6], seas_stats_table->event[7], + seas_stats_table->event[8], seas_stats_table->event[9], + seas_stats_table->event[10], seas_stats_table->event[11], + seas_stats_table->event[12], seas_stats_table->event[13], + seas_stats_table->event[14]))) { + goto error; + } else { + if(k > STATS_BUF_SIZE - j) { + j = STATS_BUF_SIZE; + goto send; + } + j += k; + } + if(0 > (k = snprintf(&buf[j], STATS_BUF_SIZE - j, + "Started Transactions: %d\nTerminated " + "Transactions:%d\nReceived replies:%d\nReceived:%d\n", + seas_stats_table->started_transactions, + seas_stats_table->finished_transactions, + seas_stats_table->received_replies, + seas_stats_table->received))) { + goto error; + } else { + if(k > STATS_BUF_SIZE - j) { + j = STATS_BUF_SIZE; + goto send; + } + j += k; + } send: - lock_release(seas_stats_table->mutex); -again:/*mutex is released*/ - k=write(sock,buf,j); - if(k<0){ - switch(errno){ - case EINTR: - goto again; - case EPIPE: - return -2; - } - } - writen+=k; - if(writenmutex); - return -1; + lock_release(seas_stats_table->mutex); +again: /*mutex is released*/ + k = write(sock, buf, j); + if(k < 0) { + switch(errno) { + case EINTR: + goto again; + case EPIPE: + return -2; + } + } + writen += k; + if(writen < j) + goto again; + return writen; +error: /*mutex is locked*/ + lock_release(seas_stats_table->mutex); + return -1; } void stats_reply(void) { - lock_get(seas_stats_table->mutex); - seas_stats_table->received_replies++; - lock_release(seas_stats_table->mutex); + lock_get(seas_stats_table->mutex); + seas_stats_table->received_replies++; + lock_release(seas_stats_table->mutex); } - - diff --git a/src/modules/seas/statistics.h b/src/modules/seas/statistics.h index e518903f196..225e000b73a 100644 --- a/src/modules/seas/statistics.h +++ b/src/modules/seas/statistics.h @@ -21,9 +21,9 @@ #include #include -#include "../../core/hashes.h"/* for TABLE_ENTRIES define*/ -#include "../../core/locking.h"/* for TABLE_ENTRIES define*/ -#include "../../modules/tm/h_table.h"/* for struct cell*/ +#include "../../core/hashes.h" /* for TABLE_ENTRIES define*/ +#include "../../core/locking.h" /* for TABLE_ENTRIES define*/ +#include "../../modules/tm/h_table.h" /* for struct cell*/ #define STATS_CELLS 50 #define UAS_T 0 #define UAC_T 1 @@ -36,34 +36,37 @@ */ struct statscell { - /** 0 = UAS, 1 = UAC*/ - char type; - /**difference between a request_event and a reply_action*/ - union { - struct { - struct timeval as_relay; - struct timeval event_sent; - struct timeval action_recvd; - } uas; - struct { - struct timeval action_recvd; - struct timeval event_sent; - struct timeval action_reply_sent; - } uac; - }u; + /** 0 = UAS, 1 = UAC*/ + char type; + /**difference between a request_event and a reply_action*/ + union + { + struct + { + struct timeval as_relay; + struct timeval event_sent; + struct timeval action_recvd; + } uas; + struct + { + struct timeval action_recvd; + struct timeval event_sent; + struct timeval action_reply_sent; + } uac; + } u; }; /** Transactions statistics table */ struct statstable { - gen_lock_t *mutex; - unsigned int dispatch[15]; - unsigned int event[15]; - unsigned int action[15]; - unsigned int started_transactions; - unsigned int finished_transactions; - unsigned int received_replies; - unsigned int received; + gen_lock_t *mutex; + unsigned int dispatch[15]; + unsigned int event[15]; + unsigned int action[15]; + unsigned int started_transactions; + unsigned int finished_transactions; + unsigned int received_replies; + unsigned int received; }; extern struct statstable *seas_stats_table; @@ -71,7 +74,7 @@ extern struct statstable *seas_stats_table; /** * Initialize and destroy statistics table */ -struct statstable* init_seas_stats_table(void); +struct statstable *init_seas_stats_table(void); int stop_stats_server(void); void destroy_seas_stats_table(void); /** Statistics server process @@ -79,7 +82,7 @@ void destroy_seas_stats_table(void); */ void serve_stats(int fd); int start_stats_server(char *socket); -int print_stats_info(int f,int sock); +int print_stats_info(int f, int sock); /** * Statistics functions */ @@ -87,9 +90,9 @@ void as_relay_stat(struct cell *t); void event_stat(struct cell *t); void action_stat(struct cell *t); void stats_reply(void); -#define receivedplus() \ - do{ \ - lock_get(seas_stats_table->mutex); \ - seas_stats_table->received++; \ - lock_release(seas_stats_table->mutex); \ - }while(0) +#define receivedplus() \ + do { \ + lock_get(seas_stats_table->mutex); \ + seas_stats_table->received++; \ + lock_release(seas_stats_table->mutex); \ + } while(0) diff --git a/src/modules/seas/utils.c b/src/modules/seas/utils.c index 76c2c6af5e2..b0017e61f18 100644 --- a/src/modules/seas/utils.c +++ b/src/modules/seas/utils.c @@ -58,138 +58,141 @@ #define MAX_ERROR 32 -static inline int memstr(char *haystack,int hlen,char *needle,int nlen); +static inline int memstr(char *haystack, int hlen, char *needle, int nlen); -int buffered_printer(FILE* infd) +int buffered_printer(FILE *infd) { - int i,k=0,retval; - char *missatge=0,*myerror=""; - struct sip_msg msg; - static char mybuffer[1400]; - static int end=0,last=0; + int i, k = 0, retval; + char *missatge = 0, *myerror = ""; + struct sip_msg msg; + static char mybuffer[1400]; + static int end = 0, last = 0; - while((i=fread(&mybuffer[last],1,1400-last,infd))==1400-last){ - if((end=memstr(mybuffer,last+i,"\n\n\n",3))<0){ - last+=i; - return 0; - }else{ - end+=3; - while(end<1400 && (mybuffer[end]=='\n' || mybuffer[end]=='.' || mybuffer[end]=='\r')) - end++; - if((missatge=pkg_malloc(end))==0){ - myerror="Out of memory !!\n"; - goto error; - } - memset(missatge,0,end); - memcpy(missatge,mybuffer,end); - memset(&msg,0,sizeof(struct sip_msg)); - msg.buf=missatge; - msg.len=end; - if(!parse_msg(msg.buf,msg.len,&msg)) - print_msg_info(stdout,&msg); - printf("PARSED:%d,last=%d,end=%d\n",k++,last,end); - free_sip_msg(&msg); - pkg_free(missatge); - missatge = NULL; - memmove(mybuffer,&mybuffer[end],1400-end); - last=1400-end; - } - } - retval=0; - goto exit; + while((i = fread(&mybuffer[last], 1, 1400 - last, infd)) == 1400 - last) { + if((end = memstr(mybuffer, last + i, "\n\n\n", 3)) < 0) { + last += i; + return 0; + } else { + end += 3; + while(end < 1400 + && (mybuffer[end] == '\n' || mybuffer[end] == '.' + || mybuffer[end] == '\r')) + end++; + if((missatge = pkg_malloc(end)) == 0) { + myerror = "Out of memory !!\n"; + goto error; + } + memset(missatge, 0, end); + memcpy(missatge, mybuffer, end); + memset(&msg, 0, sizeof(struct sip_msg)); + msg.buf = missatge; + msg.len = end; + if(!parse_msg(msg.buf, msg.len, &msg)) + print_msg_info(stdout, &msg); + printf("PARSED:%d,last=%d,end=%d\n", k++, last, end); + free_sip_msg(&msg); + pkg_free(missatge); + missatge = NULL; + memmove(mybuffer, &mybuffer[end], 1400 - end); + last = 1400 - end; + } + } + retval = 0; + goto exit; error: - printf("Error on %s",myerror); - retval=1; + printf("Error on %s", myerror); + retval = 1; exit: - if(missatge) - pkg_free(missatge); - return retval; + if(missatge) + pkg_free(missatge); + return retval; } -int coded_buffered_printer(FILE* infd) +int coded_buffered_printer(FILE *infd) { - int i,lastlast; - char spaces[50]; - static char mybuffer[1500]; - static int size=0,last=0; + int i, lastlast; + char spaces[50]; + static char mybuffer[1500]; + static int size = 0, last = 0; - memcpy(spaces," ",2); + memcpy(spaces, " ", 2); - do{ - lastlast=1500-last; - i=fread(&mybuffer[last],1,lastlast,infd); - printf("read i=%d\n",i); - if(i==0) - break; - if(size==0){ - size=GET_PAY_SIZE(mybuffer); - printf("size=%d\n",size); - last+=i; - } - if(last>=size){ - printf("should print message: last=%d, size=%d\n",last,size); - if(print_encoded_msg(stdout,mybuffer,spaces)<0){ - printf("Unable to print encoded msg\n"); - return -1; - } - if(last>size){ - memmove(mybuffer,&mybuffer[size],last-size); - last=last-size; - }else - last=0; - size=0; - } - }while(i>0 && i==lastlast); + do { + lastlast = 1500 - last; + i = fread(&mybuffer[last], 1, lastlast, infd); + printf("read i=%d\n", i); + if(i == 0) + break; + if(size == 0) { + size = GET_PAY_SIZE(mybuffer); + printf("size=%d\n", size); + last += i; + } + if(last >= size) { + printf("should print message: last=%d, size=%d\n", last, size); + if(print_encoded_msg(stdout, mybuffer, spaces) < 0) { + printf("Unable to print encoded msg\n"); + return -1; + } + if(last > size) { + memmove(mybuffer, &mybuffer[size], last - size); + last = last - size; + } else + last = 0; + size = 0; + } + } while(i > 0 && i == lastlast); - if(i==0) - return 0; - else - return 1; + if(i == 0) + return 0; + else + return 1; } -int print_msg_info(FILE* fd,struct sip_msg* msg) +int print_msg_info(FILE *fd, struct sip_msg *msg) { - char *payload=0; - char *prefix=0; - int retval=-1; - if((prefix=pkg_malloc(500))==0){ - printf("OUT OF MEMORY !!!\n"); - return -1; - } - memset(prefix,0,500); - strcpy(prefix," "); + char *payload = 0; + char *prefix = 0; + int retval = -1; + if((prefix = pkg_malloc(500)) == 0) { + printf("OUT OF MEMORY !!!\n"); + return -1; + } + memset(prefix, 0, 500); + strcpy(prefix, " "); - if(parse_headers(msg,HDR_EOH_F,0)<0) - goto error; - if(!(payload=pkg_malloc(MAX_ENCODED_MSG + MAX_MESSAGE_LEN))) - goto error; - if(encode_msg(msg,payload,MAX_ENCODED_MSG + MAX_MESSAGE_LEN)<0){ - printf("Unable to encode msg\n"); - goto error; - } - if(print_encoded_msg(fd,payload,prefix)<0){ - printf("Unable to print encoded msg\n"); - pkg_free(payload); - goto error; - } - pkg_free(payload); - retval =0; + if(parse_headers(msg, HDR_EOH_F, 0) < 0) + goto error; + if(!(payload = pkg_malloc(MAX_ENCODED_MSG + MAX_MESSAGE_LEN))) + goto error; + if(encode_msg(msg, payload, MAX_ENCODED_MSG + MAX_MESSAGE_LEN) < 0) { + printf("Unable to encode msg\n"); + goto error; + } + if(print_encoded_msg(fd, payload, prefix) < 0) { + printf("Unable to print encoded msg\n"); + pkg_free(payload); + goto error; + } + pkg_free(payload); + retval = 0; error: - if(prefix) - pkg_free(prefix); - return retval; + if(prefix) + pkg_free(prefix); + return retval; } -static inline int memstr(char *haystack,int hlen,char *needle,int nlen) +static inline int memstr(char *haystack, int hlen, char *needle, int nlen) { - int i=0; + int i = 0; - if(nlen>hlen) - return -1; - while(i<=(hlen-nlen) && (haystack[i]!=needle[0] || memcmp(&haystack[i],needle,nlen))) - i++; - if(i>(hlen-nlen)) - return -1; - else - return i; + if(nlen > hlen) + return -1; + while(i <= (hlen - nlen) + && (haystack[i] != needle[0] || memcmp(&haystack[i], needle, nlen))) + i++; + if(i > (hlen - nlen)) + return -1; + else + return i; } diff --git a/src/modules/seas/utils.h b/src/modules/seas/utils.h index 22548caf3df..3f8cf6b3042 100644 --- a/src/modules/seas/utils.h +++ b/src/modules/seas/utils.h @@ -21,6 +21,6 @@ #include "../../core/parser/msg_parser.h" -int buffered_printer(FILE* infd); -int print_msg_info(FILE* fd,struct sip_msg* msg); -int coded_buffered_printer(FILE* infd); +int buffered_printer(FILE *infd); +int print_msg_info(FILE *fd, struct sip_msg *msg); +int coded_buffered_printer(FILE *infd); diff --git a/src/modules/seas/xaddress.h b/src/modules/seas/xaddress.h index b878d35d2ce..828f974de09 100644 --- a/src/modules/seas/xaddress.h +++ b/src/modules/seas/xaddress.h @@ -23,6 +23,4 @@ #define ONLY_URIS 0x01 #define SEGREGATE 0x02 #define ALSO_RURI 0x04 -#define JUNIT 0x08 - - +#define JUNIT 0x08