// display pmem pool void pmemalloc_display() { struct clump* clp; size_t sz; size_t prev_sz; int state; clp = (struct clump *)ABS_PTR((struct clump *) PMEM_CLUMP_OFFSET); fprintf(stdout, "----------------------------------------------------------\n"); while (1) { sz = clp->size & ~PMEM_STATE_MASK; prev_sz = clp->prevsize; state = clp->size & PMEM_STATE_MASK; fprintf(stdout, "%lu (%d)(%p)(%lu) -> ", sz, state, (struct clump *)REL_PTR(clp), prev_sz); if (clp->size == 0) break; clp = (struct clump *) ((uintptr_t) clp + sz); } fprintf(stdout, "\n"); fprintf(stdout, "----------------------------------------------------------\n"); fflush(stdout); }
/** * Returns how many bytes in *where have been used * * TODO this is little shitty, someone should unify all the param flavours * to a sigle universal type of parameter (to_param,param,disposition_param) * the way is done here, at least, we dont have the parameter-hanling code spread all around. */ int encode_parameters(unsigned char *where,void *pars,char *hdrstart,void *_body,char to) { 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; 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; 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; 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; 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; 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; 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; 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; 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:[email protected];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(i<paramlen){ i++; if(paramstart[i]==';'){/*no '=' found !*/ where[j++]=(unsigned char)(¶mstart[i+1]-hdrstart); where[j++]=(unsigned char)(¶mstart[i+1]-hdrstart); } if(paramstart[i]=='='){/* '=' found, look for the next ';' and let 'i' pointing to it*/ where[j++]=(unsigned char)(¶mstart[i+1]-hdrstart); for(;i<paramlen&¶mstart[i]!=';';i++); if(paramstart[i]==';') where[j++]=(unsigned char)(¶mstart[i+1]-hdrstart); } } where[j++]=(unsigned char)(¶mstart[i+1]-hdrstart); if(j%2 == 0)/*this is because maybe the LAST parameter doesn't have an '='*/ where[j++]=(unsigned char)(¶mstart[i+1]-hdrstart); return j; } return 0; }
/*The XURI is one of the most important parts in SEAS, as * most of the SIP MESSAGE structured headers (that is, * headers which have a well-specified body construction) * use the URI as the body (ie. via, route, record-route, * contact, from, to, RURI) * * the XURI is a codified structure of flags and pointers * that ease the parsing of the URI string. * * 1: The first byte of the structure, is a * HEADER_START-based pointer to the beginning of the URI * (including the "sip:"). * 1: The next byte is the length of the uri, so URIMAX * is 256 (enough...) * 2: Flags specifying the parts that are present in the URI * * as follows: * 1: first byte * SIP_OR_TEL_F 0x01 it is SIP or TEL uri. * SECURE_F 0x02 it is secure or not (SIPS,TELS) * USER_F 0x04 it as a user part (user@host) * PASSWORD_F 0x08 it has a password part * HOST_F 0x10 it has a host part * PORT_F 0x20 it has a port part * PARAMETERS_F 0x40 it has a port part * HEADERS_F 0x80 it has a port part * 1: second byte * TRANSPORT_F 0x01 it has other parameters * TTL_F 0x02 it has headers * USER_F 0x04 it has the transport parameter * METHOD_F 0x08 it has the ttl parameter * MADDR_F 0x10 it has the user parameter * LR_F 0x20 it has the method parameter * * All the following bytes are URI_START-based pointers to * the fields that are present in the uri, as specified by * the flags. They must appear in the same order shown in * the flags, and only appear if the flag was set to 1. * * the end of the field, will be the place where the * following pointer points to, minus one (note that all the * fields present in a URI are preceded by 1 character, ie * sip[:user][:passwod][@host][:port][;param1=x][;param2=y][?hdr1=a][&hdr2=b]$p * it will be necessary to have a pointer at the end, * pointing two past the end of the uri, so that the length * of the last header can be computed. * * The reason to have the OTHER and HEADERS flags at the * beginning(just after the strictly-uri stuff), is that it * will be necessary to know the length of the parameters * section and the headers section. * * The parameters can * appear in an arbitrary order, so they won't be following * the convention of transport-ttl-user-method-maddr-lr, so * we can't rely on the next pointer to compute the length * of the previous pointer field, as the ttl param can * appear before the transport param. so the parameter * pointers must have 2 bytes: pointer+length. * */ int encode_uri2(char *hdr,int hdrlen,str uri_str, struct sip_uri *uri_parsed,unsigned char *payload) { int i=4,j;/* 1*pointer+1*len+2*flags*/ unsigned int scheme; unsigned char flags1=0,flags2=0,uriptr; 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 * 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){ case SIP_URI_T: flags1 |= SIP_OR_TEL_F; break; case SIPS_URI_T: flags1 |= (SIP_OR_TEL_F|SECURE_F); break; case TEL_URI_T: break; case TELS_URI_T: flags1 |= SECURE_F; break; 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(i<j) goto error; return i; error: return -1; }
// pmemalloc_reserve -- allocate memory, volatile until pmemalloc_activate() static void *pmemalloc_reserve(size_t size) { size_t nsize; if (size <= 64) { nsize = 128; } else { size_t temp = 63; nsize = 64 + ((size + 63) & ~temp); } //cerr<<"size :: "<<size<<" nsize :: "<<nsize<<endl; struct clump *clp; struct clump* next_clp; int loop = 0; DEBUG("size= %zu", nsize); if (prev_clp != NULL) { clp = prev_clp; // printf("prev_clp=%p\n", prev_clp); } else { clp = (struct clump *)ABS_PTR((struct clump *) PMEM_CLUMP_OFFSET); } DEBUG("pmp=%p clp= %p, size of clp=%d size of struct clump =%d", pmp, clp, sizeof(clp), sizeof(struct clump)); /* first fit */ check: //unsigned int itr = 0; while (clp->size) { // DEBUG("************** itr :: %lu ", itr++); size_t sz = clp->size & ~PMEM_STATE_MASK; int state = clp->size & PMEM_STATE_MASK; DEBUG("size : %lu state : %d", sz, state); if (nsize <= sz) { if (state == PMEM_STATE_FREE) { void *ptr = (void *) (uintptr_t) clp + PMEM_CHUNK_SIZE - (uintptr_t) pmp; size_t leftover = sz - nsize; DEBUG("fit found ptr 0x%lx, leftover %lu bytes", ptr, leftover); if (leftover >= PMEM_CHUNK_SIZE * 2) { struct clump *newclp; newclp = (struct clump *) ((uintptr_t) clp + nsize); DEBUG("splitting: [0x%lx] new clump", (struct clump *)REL_PTR(newclp)); /* * can go ahead and start fiddling with * this freely since it is in the middle * of a free clump until we change fields * in *clp. order here is important: * 1. initialize new clump * 2. persist new clump * 3. initialize existing clump do list * 4. persist existing clump * 5. set new clump size, RESERVED * 6. persist existing clump */ PM_EQU((newclp->size), (leftover | PMEM_STATE_FREE)); PM_EQU((newclp->prevsize), (nsize)); pmem_persist(newclp, sizeof(*newclp), 0); next_clp = (struct clump *) ((uintptr_t) newclp + leftover); PM_EQU((next_clp->prevsize), (leftover)); pmem_persist(next_clp, sizeof(*next_clp), 0); PM_EQU((clp->size), (nsize | PMEM_STATE_RESERVED)); pmem_persist(clp, sizeof(*clp), 0); //DEBUG("validate new clump %p", REL_PTR(newclp)); //DEBUG("validate orig clump %p", REL_PTR(clp)); //DEBUG("validate next clump %p", REL_PTR(next_clp)); } else { DEBUG("no split required"); PM_EQU((clp->size), (sz | PMEM_STATE_RESERVED)); pmem_persist(clp, sizeof(*clp), 0); next_clp = (struct clump *) ((uintptr_t) clp + sz); PM_EQU((next_clp->prevsize), (sz)); pmem_persist(next_clp, sizeof(*next_clp), 0); //DEBUG("validate orig clump %p", REL_PTR(clp)); //DEBUG("validate next clump %p", REL_PTR(next_clp)); } prev_clp = clp; return ABS_PTR(ptr); } } clp = (struct clump *) ((uintptr_t) clp + sz); DEBUG("next clump :: [0x%lx]", (struct clump *)REL_PTR(clp)); } if (loop == 0) { DEBUG("LOOP "); loop = 1; clp = (struct clump *)ABS_PTR((struct clump *) PMEM_CLUMP_OFFSET); goto check; } printf("no free memory of size %lu available \n", nsize); printf("Increase the size of the PM pool:\n"); printf("Increase PSEGMENT_RESERVED_REGION_SIZE in benchmarks/echo/echo/include/pm_instr.h\n"); //display(); errno = ENOMEM; exit(EXIT_FAILURE); return NULL; }
/* Encoder for vias. * Returns the length of the encoded structure in bytes * FORMAT (byte meanings): * 1: flags * */ 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; }