/* Encoder for route/record-route units (may be inside an aggegated * Route/RRoute header, see [rfc3261, 7.3.1, page 30] ). * Returns the length of the encoded structure in bytes * FORMAT (byte meanings): * 1: flags * 0x01 : there is a Display Name * 1: length of the XURI-encoded uri in bytes. * [2]: optionally, 1 HDR-based ptr to the displayname + the length of the name * N: the XURI-encoded URI. * [N:] optionally, HDR-based pointers to the different header-parameters * */ int encode_route(char *hdrstart,int hdrlen,rr_t *body,unsigned char *where) { int i=2,j=0;/* 1*flags + 1*URI_len*/ unsigned char flags=0; struct sip_uri puri; if(body->nameaddr.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; }
/* Encoder for contacts. * Returns the length of the encoded structure in bytes * FORMAT (byte meanings): * 1: flags * 0x01 : there is a Display Name * 0x02 : there is a Q parameter * 0x04 : there is an EXPIRES parameter * 0x08 : there is a RECEIVED parameter * 0x10 : there is a METHOD parameter * 1: length of the XURI-encoded uri in bytes. * [2]: optionally, 1 HDR-based ptr to the displayname + the length of the name * [2]: optionally, 1 HDR-based ptr to the q + the length of the q * [2]: optionally, 1 HDR-based ptr to the expires + the length of the expires * [2]: optionally, 1 HDR-based ptr to the received param + the length of the param * [2]: optionally, 1 HDR-based ptr to the method + the length of the method parameter * N: the XURI-encoded URI. * [N:] optionally, HDR-based pointers to the different header-parameters * */ 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; 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...*/ i+=encode_parameters(&where[i],body->params,hdrstart,body,'n'); return i; }
/* Encoder for From and To headers. * Returns the length of the encoded structure in bytes * FORMAT (byte meanings): * 1: flags * 0x10 : there is a Display Name * 0x20 : there is a tag parameter * 0x40 : there are other parameters * 1: length of the XURI-encoded uri in bytes. * [2]: optionally, 1 HDR-based ptr to the displayname + the length of the name * [2]: optionally, 1 HDR-based ptr to the tag + the length of the tag parameter * N: the XURI-encoded URI. * [N:] optionally, HDR-based pointers to the different header-parameters * */ int encode_to_body(char *hdrstart,int hdrlen,struct to_body *body,unsigned char *where) { int i=2,j=0;/* 1*flags + 1*URI_len*/ unsigned char flags=0; struct sip_uri puri; 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; }
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; 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; }
/* This function extracts meta-info from the sip_msg structure and * formats it so that it can be used to rapidly access the message structured * parts. * * RETURNS: LENGTH of structure on success, <0 if failure * if there was failure, you dont need to pkg_free the payload (it is done inside). * if there was success, you __NEED_TO_PKG_FREE_THE_PAYLOAD__ from the calling function. * * The encoded meta-info is composed by 3 sections: * * MSG_META_INFO: * 2: short int in network-byte-order, if <100, the msg is a REQUEST and the int * is the code of the METHOD. if >100, it is a RESPONSE and the int is the code * of the response. * 2: short int in NBO: payload-start based pointer (index) to where the SIP MSG starts. * 2: short int in NBO: the sip-message length * 2: METHOD or CODE string SIP-START-based pointer and length * 2: R-URI or REASON PHRASE string SIP-START-based pointer and length * 2: VERSION string SIP-START-based pointer and length * 2: short int in NBO: start of the content of the SIP message * [1+N]: in case this is a request, the length of the encoded-uri and the encoded-uri * 1: how many present headers have been found. * * MSG_HEADERS_INDEX: * N*3: groups of 3 bytes, each one describing a header struct: the first byte * is a letter that corresponds to a header type, the second and third bytes are a NBO * inidex to where this struct begins within the HEADERS_META_INFO section. * * HEADERS_META_INFO: * M: all the codified headers meta info structs one after another * * SIP_MSG: * the SIP message as it has been received. * * The length of the structure, will be ((short*)payload)[1] + ((short*)payload)[2] * * 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 i,j,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(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; else if(ms->type == SIP_REPLY) request=0; else { myerror="message is neither request nor response"; goto error; } if(request) { for(h=0; h<32; j=(0x01<<h),h++) if(j & ms->u.request.method_value) break; } else { h=(unsigned short)(ms->u.reply.statuscode); } if(h==32) { /*statuscode wont 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 * 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[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; }