/** * creates an as_event in shared memory and returns its address or NULL if error. * event_length(4) UNSIGNED INT includes the length 4 bytes itself * type(1), * processor_id(4), * flags(4), * transport(1). * src_ip_len(1), * src_ip(4 or 16), * dst_ip_len(1), * dst_ip(4 or 16), * src_port(2), * dst_port(2), * */ 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; if(!(buffer=shm_malloc(ENCODED_MSG_SIZE))){ LM_ERR("create_as_event_t Out Of Memory !!\n"); return 0; } *evt_len=0; /*leave 4 bytes for event length*/ k=4; /*type*/ buffer[k++]=(unsigned char)SL_REQ_IN; /*processor_id*/ buffer[k++]=(unsigned char)processor_id; /*flags*/ 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; /*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; /*length of event (hdr+payload-4), copied at the beginning*/ 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); return buffer; error: if(buffer) shm_free(buffer); return 0; }
int coded_buffered_printer(int infd) { int i,lastlast; char spaces[50]; static char mybuffer[1500]; static int size=0,last=0; memcpy(spaces," ",2); do{ lastlast=1500-last; i=read(infd,&mybuffer[last],lastlast); 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(1,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; }
/** * creates an as_event in shared memory and returns its address or NULL if error. * event_length(4) UNSIGNED INT includes the length 4 bytes itself * type(1), * flags(4), * transport(1). * src_ip_len(1), * src_ip(4 or 16), * dst_ip_len(1), * dst_ip(4 or 16), * src_port(2), * dst_port(2), * hash index(4), * label(4), * [cancelled hash_index,label] * */ 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 short int port; unsigned int k,len; char *buffer=NULL; struct cell *originalT; originalT=0; 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{ /**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; /*type*/ buffer[k++]=(unsigned char)T_REQ_IN; /*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){ LM_DBG("new CANCEL\n"); originalT=seas_f.tmb.t_lookup_original_t(msg); if(!originalT || originalT==T_UNDEFINED){ /** we dont even pass the unknown CANCEL to JAIN*/ LM_WARN("CANCEL does not match any existing transaction!!\n"); goto error; }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; /*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; /*hash_index*/ 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); /*hash_index*/ 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; } /*length of event (hdr+payload-4), copied at the beginning*/ 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); return buffer; error: if(buffer) shm_free(buffer); return 0; }
/* 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; }