int add_lb_dsturi( struct lb_data *data, int id, int group, char *uri, char* resource, unsigned int flags) { struct lb_res_str_list *lb_rl; struct lb_res_str *r; struct lb_dst *dst; struct lb_resource *res; struct sip_uri puri; struct proxy_l *proxy; union sockaddr_union sau; int len; int i; LM_DBG("uri=<%s>, grp=%d, res=<%s>\n",uri, group, resource); /* check uri */ len = strlen(uri); if(parse_uri(uri, len, &puri)!=0 ) { LM_ERR("bad uri [%.*s] for destination\n", len, uri); return -1; } /* parse the resources string */ lb_rl = parse_resources_list( resource, 1); if (lb_rl==NULL) { LM_ERR("failed to parse resourse string <%s>\n",resource); return -1; } /*add new destination */ dst = (struct lb_dst*)shm_malloc( sizeof(struct lb_dst) + lb_rl->n*sizeof(struct lb_resource_map) + len + (3+2*sizeof(struct lb_dst*))); if (dst==NULL) { LM_ERR("failed to get shmem\n"); goto error; } memset( dst, 0, sizeof(struct lb_dst)+ lb_rl->n*sizeof(struct lb_resource_map) + len + (3+2*sizeof(struct lb_dst*)) ); dst->rmap = (struct lb_resource_map*)(dst+1); dst->uri.s = (char*)(dst->rmap + lb_rl->n); dst->uri.len = len; memcpy( dst->uri.s , uri, len); dst->profile_id.s = dst->uri.s + len; dst->profile_id.len = snprintf(dst->profile_id.s, 2+2*sizeof(struct lb_dst*), "%X", id); dst->id = id; dst->group = group; dst->rmap_no = lb_rl->n; dst->flags = flags; /* add or update resource list */ for( i=0 ; i<lb_rl->n ; i++) { r = lb_rl->resources + i; LM_DBG(" setting for uri=<%s> (%d) resource=<%.*s>, val=%d\n", uri, data->dst_no+1, r->name.len, r->name.s, r->val); res = get_resource_by_name( data, &r->name); if (res==NULL) { /* add new resource */ res = add_lb_resource(data, &r->name); if (res==NULL) { LM_ERR("failed to create new resource\n"); goto error; } } /* set the proper bit in the resource */ if (lb_set_resource_bitmask( res, data->dst_no)==-1 ) { LM_ERR("failed to set destination bit\n"); goto error; } /* set the pointer and the max load */ dst->rmap[i].resource = res; dst->rmap[i].max_load = r->val; } /* Do a SIP wise DNS-Lookup for the domain part */ proxy = mk_proxy( &puri.host, puri.port_no, puri.proto, (puri.type==SIPS_URI_T)); if (proxy==NULL) { LM_ERR("could not resolve %.*s\n", puri.host.len, puri.host.s); goto error; } hostent2ip_addr( &dst->ips[0], &proxy->host, proxy->addr_idx); dst->ports[0] = proxy->port; dst->ips_cnt = 1; LM_DBG("first dst ip addr [%s]:%d\n", ip_addr2a(&dst->ips[0]), dst->ports[0]); /* get the next available IPs from DNS */ while (dst->ips_cnt<LB_MAX_IPS && (get_next_su( proxy, &sau, 0)==0) ) { su2ip_addr( &dst->ips[dst->ips_cnt], &sau); dst->ports[dst->ips_cnt] = proxy->port; LM_DBG("additional dst ip addr [%s]:%d\n", ip_addr2a(&dst->ips[dst->ips_cnt]), dst->ports[dst->ips_cnt]); /* one more IP found */ dst->ips_cnt++; } /* free al the helper structures */ free_proxy(proxy); pkg_free(proxy); /* link at the end */ if (data->last_dst==NULL) { data->dsts = data->last_dst = dst; } else { data->last_dst->next = dst; data->last_dst = dst; } data->dst_no++; pkg_free(lb_rl); return 0; error: shm_free(dst); pkg_free(lb_rl); return -1; }
int do_lb_reset(struct sip_msg *req, struct lb_data *data) { struct usr_avp *id_avp; struct usr_avp *res_avp, *del_res_avp; int_str id_val; int_str res_val; struct dlg_cell *dlg; struct lb_dst *it_d, *last_dst; struct lb_resource *it_r; if ( (dlg=lb_dlg_binds.get_dlg())==NULL ) { LM_ERR("no dialog found for this call, LB not started\n"); return -1; } /* remove any saved AVPs */ destroy_avps(0, group_avp_name, 0); destroy_avps(0, flags_avp_name, 0); destroy_avps(0, mask_avp_name, 0); /* get previous iteration destination, if any */ last_dst = NULL; id_avp = search_first_avp(0, id_avp_name, &id_val, NULL); if( id_avp && (is_avp_str_val(id_avp) == 0) ) { for( it_d=data->dsts ; it_d ; it_d=it_d->next ) { if( it_d->id == id_val.n ) { last_dst = it_d; LM_DBG("reset LB - found previous dst %d [%.*s]\n", last_dst->id, last_dst->profile_id.len, last_dst->profile_id.s); break; } } } destroy_avps(0, id_avp_name, 0); /* any valid previous iteration ? */ if(last_dst == NULL) { /* simply delete all possible resources */ destroy_avps(0, res_avp_name, 1); } else { /* search and clean up previous iteration resources, if any */ res_avp = search_first_avp(0, res_avp_name, &res_val, NULL); while (res_avp) { if ( (it_r=get_resource_by_name( data, &res_val.s))!=NULL ) { if( lb_dlg_binds.unset_profile(dlg, &last_dst->profile_id, it_r->profile) != 1 ) LM_ERR("reset LB - failed to remove from profile [%.*s]->" "[%.*s]\n", res_val.s.len, res_val.s.s, last_dst->profile_id.len, last_dst->profile_id.s ); } else { LM_WARN("reset LB - ignore unknown previous resource " "[%.*s]\n", res_val.s.len, res_val.s.s); } del_res_avp = res_avp; res_avp = search_next_avp(del_res_avp, &res_val); destroy_avp(del_res_avp); } } return 0; }
int add_lb_dsturi( struct lb_data *data, int id, int group, char *uri, char* resource, unsigned int flags) { struct lb_res_str_list *lb_rl; struct lb_res_str *r; struct lb_dst *dst; struct lb_resource *res; int len; int i; LM_DBG("uri=<%s>, grp=%d, res=<%s>\n",uri, group, resource); /* parse the resources string */ lb_rl = parse_resources_list( resource, 1); if (lb_rl==NULL) { LM_ERR("failed to parse resourse string <%s>\n",resource); return -1; } len = strlen(uri); /*add new destination */ dst = (struct lb_dst*)shm_malloc( sizeof(struct lb_dst) + lb_rl->n*sizeof(struct lb_resource_map) + len + (3+2*sizeof(struct lb_dst*))); if (dst==NULL) { LM_ERR("failed to get shmem\n"); goto error; } memset( dst, 0, sizeof(struct lb_dst)+ lb_rl->n*sizeof(struct lb_resource_map) + len + (3+2*sizeof(struct lb_dst*)) ); dst->rmap = (struct lb_resource_map*)(dst+1); dst->uri.s = (char*)(dst->rmap + lb_rl->n); dst->uri.len = len; memcpy( dst->uri.s , uri, len); dst->profile_id.s = dst->uri.s + len; dst->profile_id.len = snprintf(dst->profile_id.s, 2+2*sizeof(struct lb_dst*), "%X", id); dst->id = id; dst->group = group; dst->rmap_no = lb_rl->n; dst->flags = flags; /* add or update resource list */ for( i=0 ; i<lb_rl->n ; i++) { r = lb_rl->resources + i; LM_DBG(" setting for uri=<%s> (%d) resource=<%.*s>, val=%d\n", uri, data->dst_no+1, r->name.len, r->name.s, r->val); res = get_resource_by_name( data, &r->name); if (res==NULL) { /* add new resource */ res = add_lb_resource(data, &r->name); if (res==NULL) { LM_ERR("failed to create new resource\n"); goto error; } } /* set the proper bit in the resource */ if (lb_set_resource_bitmask( res, data->dst_no)==-1 ) { LM_ERR("failed to set destination bit\n"); goto error; } /* set the pointer and the max load */ dst->rmap[i].resource = res; dst->rmap[i].max_load = r->val; } /* link at the end */ if (data->last_dst==NULL) { data->dsts = data->last_dst = dst; } else { data->last_dst->next = dst; data->last_dst = dst; } data->dst_no++; pkg_free(lb_rl); return 0; error: shm_free(dst); pkg_free(lb_rl); return -1; }
int lb_route(struct sip_msg *req, int group, struct lb_res_str_list *rl, unsigned int flags, struct lb_data *data, int reuse) { /* resources for previous iteration */ static struct lb_resource **res_prev = NULL; static unsigned int res_prev_size = 0; /* resources for new iteration */ static struct lb_resource **res_new = NULL; static unsigned int res_new_size = 0; /* probed destinations bitmap */ static unsigned int *dst_bitmap = NULL; static unsigned int bitmap_size = 0; /* selected destinations buffer */ static struct lb_dst **dsts = NULL; static unsigned int dsts_size = 0; /* control vars */ struct lb_resource **res_cur; int res_prev_n, res_new_n, res_cur_n; struct lb_dst **dsts_cur; struct lb_dst *last_dst, *dst; unsigned int dsts_size_cur, dsts_size_max; unsigned int *dst_bitmap_cur; unsigned int bitmap_size_cur; struct dlg_cell *dlg; /* AVP related vars */ struct usr_avp *group_avp; struct usr_avp *flags_avp; struct usr_avp *mask_avp; struct usr_avp *id_avp; struct usr_avp *res_avp; int_str group_val; int_str flags_val; int_str mask_val; int_str id_val; int_str res_val; /* iterators, e.t.c. */ struct lb_dst *it_d; struct lb_resource *it_r; int load, it_l; int i, j, cond; /* init control vars state */ res_cur = NULL; res_cur_n = res_prev_n = res_new_n = 0; last_dst = dst = NULL; dst_bitmap_cur = NULL; /* search and fill new resources references if we should not reuse previous iteration data */ if( !reuse ) { res_new_n = rl->n; /* adjust size of statically allocated buffer */ if( res_new_n > res_new_size ) { res_new = (struct lb_resource **)pkg_realloc (res_new, (res_new_n * sizeof(struct lb_resource *))); if( res_new == NULL ) { res_new_size = 0; LM_ERR("no more pkg mem - resources ptr buffer realloc " "failure\n"); return -1; } res_new_size = res_new_n; } /* fill resource references */ for( it_r=data->resources,i=0 ; it_r ; it_r=it_r->next ) { if( search_resource_str(rl, &it_r->name) ) { res_new[i++] = it_r; LM_DBG("initial call of LB - found requested %d/%d " "resource [%.*s]\n", i, res_new_n, it_r->name.len, it_r->name.s); } } if( i != res_new_n ) { LM_ERR("initial call of LB - unknown resource found in " "input string\n"); return -1; } /* set 'res_new' as current iteration buffer */ res_cur = res_new; res_cur_n = res_new_n; } /* always search for previous iteration data, no matter if we will reuse it or not */ group_avp = search_first_avp(0, group_avp_name, &group_val, NULL); flags_avp = search_first_avp(0, flags_avp_name, &flags_val, NULL); mask_avp = search_first_avp(0, mask_avp_name, &mask_val, NULL); id_avp = search_first_avp(0, id_avp_name, &id_val, NULL); /* sanity checks for fetched AVPs */ if( group_avp && !(is_avp_str_val(group_avp) == 0) ) { destroy_avp(group_avp); group_avp = NULL; } if( flags_avp && !(is_avp_str_val(flags_avp) == 0) ) { destroy_avp(flags_avp); flags_avp = NULL; } if( mask_avp && !(is_avp_str_val(mask_avp) != 0) ) { destroy_avp(mask_avp); mask_avp = NULL; } if( id_avp && !(is_avp_str_val(id_avp) == 0) ) { destroy_avp(id_avp); id_avp = NULL; } /* get previous iteration destination, if any */ if( id_avp ) { for( it_d=data->dsts ; it_d ; it_d=it_d->next ) { if( it_d->id == id_val.n ) { last_dst = it_d; LM_DBG("%s call of LB - found previous dst %d [%.*s]\n", (reuse ? "sequential" : "initial"), last_dst->id, last_dst->profile_id.len, last_dst->profile_id.s); break; } } } /* search and fill previous iteration resources references only if... */ if( /* we should reuse previous resources list */ reuse || /* we have 'last_dst', i.e. previous iteration was successfull and * we need to clean it up */ (last_dst != NULL) ) { do { cond = 0; /* use it here as a 'start loop again' flag */ res_prev_n = 0; res_avp = search_first_avp(0, res_avp_name, &res_val, NULL); for( ; res_avp ; res_avp=search_next_avp(res_avp, &res_val) ) { /* ignore AVPs with invalid type */ if( !(is_avp_str_val(res_avp) != 0) ) continue; if ( (it_r=get_resource_by_name( data, &res_val.s))==NULL ) { LM_WARN("%s call of LB - ignore unknown previous " "resource [%.*s]\n", (reuse?"sequential":"initial"), res_val.s.len, res_val.s.s); continue; } /* fill buffer only if buffer size not exeeded */ if( res_prev_n < res_prev_size ) { res_prev[res_prev_n] = it_r; LM_DBG("%s call of LB - found previous resource [%.*s]\n", (reuse ? "sequential" : "initial"), it_r->name.len, it_r->name.s); } res_prev_n++; } /* adjust size of statically allocated buffer */ if( res_prev_n > res_prev_size ) { /* small hack: if we need to adjust 'res_prev' buffer adjust * it according to 'res_new' size to minimize * future pkg_realloc()'s */ if( !reuse && (res_prev_n < res_new_n) ) res_prev_n = res_new_n; res_prev = (struct lb_resource **)pkg_realloc (res_prev, (res_prev_n * sizeof(struct lb_resource *))); if( res_prev == NULL ) { res_prev_size = 0; LM_ERR("no more pkg mem - previous resources ptr " "buffer realloc failure\n"); return -1; } res_prev_size = res_prev_n; cond = 1; } } while( cond ); } /* reuse previous iteration resources, group and flags */ if( reuse ) { /* set 'res_prev' as current iteration buffer */ res_cur = res_prev; res_cur_n = res_prev_n; if( res_cur_n == 0 ) { LM_ERR("sequential call of LB - cannot find previous resources\n"); return -1; } if( group_avp ) group = group_val.n; else { LM_ERR("sequential call of LB - cannot find previous group\n"); return -1; } if( flags_avp ) flags = flags_val.n; else flags = LB_FLAGS_DEFAULT; LM_DBG("sequential call of LB - found previous group %d and " "flags 0x%x\n", group, flags); } /* sanity check - double check that we have a resource list to work with */ if( (res_cur == NULL) || (res_cur_n == 0) ) { LM_ERR("%s call of LB - no resources list to work with\n", (reuse ? "sequential" : "initial")); return -1; } /* [re-]initialize/reuse destinations mask */ /* sanity check - always calculate current iteration * res_cur[]->bitmap_size */ bitmap_size_cur=(unsigned int)(-1); for( i=0 ; i<res_cur_n ; i++ ) { if( bitmap_size_cur > res_cur[i]->bitmap_size ) bitmap_size_cur = res_cur[i]->bitmap_size; } /* always try to reuse 'mask' buffer from AVP, even if we need * to reinitialize it to avoid un-neded AVP ops */ if(mask_avp && (mask_val.s.len==(bitmap_size_cur*sizeof(unsigned int)))) { dst_bitmap_cur = (unsigned int *)mask_val.s.s; } /* ...or use our static buffer */ if( dst_bitmap_cur == NULL ) { /* adjust size of statically allocated buffer */ if( bitmap_size_cur > bitmap_size ) { dst_bitmap = (unsigned int *)pkg_realloc (dst_bitmap, (bitmap_size_cur * sizeof(unsigned int))); if( dst_bitmap == NULL ) { bitmap_size = 0; LM_ERR("no more pkg mem - dst bitmap buffer realloc failed\n"); return -1; } bitmap_size = bitmap_size_cur; } dst_bitmap_cur = dst_bitmap; } /* reinitalize buffer if... */ if( (dst_bitmap_cur == dst_bitmap) || /* it is our static buffer */ !reuse /* should not reuse previous iteration data */ ) { if( reuse ) { LM_WARN("sequential call of LB - cannot %s previous mask, routing " "will be re-started", (mask_avp ? "reuse" : "find")); } memset(dst_bitmap_cur, 0xff, (bitmap_size_cur * sizeof(unsigned int))); for( i=0 ; i<res_cur_n ; i++ ) { for( j=0 ; j<bitmap_size_cur ; j++ ) dst_bitmap_cur[j] &= res_cur[i]->dst_bitmap[j]; } } /* init selected destinations buff */ dsts_cur = NULL; dsts_size_max = (flags & LB_FLAGS_RANDOM) ? data->dst_no : 1; if( dsts_size_max > 1 ) { if( dsts_size_max > dsts_size ) { dsts = (struct lb_dst **)pkg_realloc (dsts, (dsts_size_max * sizeof(struct lb_dst *))); if( dsts == NULL ) { dsts_size_max = dsts_size = 0; LM_WARN("no more pkg mem - dsts buffer realloc failed\n"); } else dsts_size = dsts_size_max; } dsts_cur = dsts; } if( dsts_cur == NULL ) { /* fallback to no-buffer / 'select first' scenario */ dsts_cur = &dst; dsts_size_max = 1; } /* be sure the dialog is created */ if ( (dlg=lb_dlg_binds.get_dlg())==NULL ) { if( lb_dlg_binds.create_dlg(req, 0) != 1 ) { LM_ERR("%s call of LB - failed to create dialog\n", (reuse ? "sequential" : "initial")); return -1; } /* get the dialog reference */ dlg = lb_dlg_binds.get_dlg(); } /* we're initialized from here and no errors could abort us */ /* remove the dialog from previous profiles, if any */ if ( (last_dst != NULL) && (res_prev_n > 0) ) { for( i=0 ; i<res_prev_n ; i++ ) { if( lb_dlg_binds.unset_profile(dlg, &last_dst->profile_id, res_prev[i]->profile) != 1 ) LM_ERR("%s call of LB - failed to remove from profile [%.*s]" "->[%.*s]\n", (reuse ? "sequential" : "initial"), res_prev[i]->profile->name.len, res_prev[i]->profile->name.s, last_dst->profile_id.len, last_dst->profile_id.s ); } } /* lock resources */ for( i=0 ; i<res_cur_n ; i++ ) lock_get(res_cur[i]->lock); /* do the load-balancing */ /* select destinations */ cond = 0; /* use it here as a 'first iteration' flag */ load = it_l = 0; dsts_size_cur = 0; for( it_d=data->dsts,i=0,j=0 ; it_d ; it_d=it_d->next ) { if( it_d->group == group ) { if( (dst_bitmap_cur[i] & (1 << j)) && ((it_d->flags & LB_DST_STAT_DSBL_FLAG) == 0) ) { /* valid destination (group & resources & status) */ if( get_dst_load(res_cur, res_cur_n, it_d, flags, &it_l) ) { /* only valid load here */ if( (it_l > 0) || (flags & LB_FLAGS_NEGATIVE) ) { /* only allowed load here */ if( !cond/*first pass*/ || (it_l > load)/*new max*/ ) { cond = 1; /* restart buffer */ dsts_size_cur = 0; } else if( it_l < load ) { /* lower availability -> new iteration */ continue; } /* add destination to to selected destinations buffer, * if we have a room for it */ if( dsts_size_cur < dsts_size_max ) { load = it_l; dsts_cur[dsts_size_cur++] = it_d; LM_DBG("%s call of LB - destination %d <%.*s> " "selected for LB set with free=%d\n", (reuse ? "sequential" : "initial"), it_d->id, it_d->uri.len, it_d->uri.s, it_l ); } } } else { LM_WARN("%s call of LB - skipping destination %d <%.*s> - " "unable to calculate free resources\n", (reuse ? "sequential" : "initial"), it_d->id, it_d->uri.len, it_d->uri.s ); } } else { LM_DBG("%s call of LB - skipping destination %d <%.*s> " "(filtered=%d , disabled=%d)\n", (reuse ? "sequential" : "initial"), it_d->id, it_d->uri.len, it_d->uri.s, ((dst_bitmap_cur[i] & (1 << j)) ? 0 : 1), ((it_d->flags & LB_DST_STAT_DSBL_FLAG) ? 1 : 0) ); } } if( ++j == (8 * sizeof(unsigned int)) ) { i++; j=0; } } /* choose one destination among selected */ if( dsts_size_cur > 0 ) { if( (dsts_size_cur > 1) && (flags & LB_FLAGS_RANDOM) ) { dst = dsts_cur[rand() % dsts_size_cur]; } else { dst = dsts_cur[0]; } } if( dst != NULL ) { LM_DBG("%s call of LB - winning destination %d <%.*s> selected " "for LB set with free=%d\n", (reuse ? "sequential" : "initial"), dst->id, dst->uri.len, dst->uri.s, load ); /* add to the profiles */ for( i=0 ; i<res_cur_n ; i++ ) { if( lb_dlg_binds.set_profile(dlg, &dst->profile_id, res_cur[i]->profile, 0) != 0 ) LM_ERR("%s call of LB - failed to add to profile [%.*s]->" "[%.*s]\n", (reuse ? "sequential" : "initial"), res_cur[i]->profile->name.len, res_cur[i]->profile->name.s, dst->profile_id.len, dst->profile_id.s); } /* set dst as used (not selected) */ for( it_d=data->dsts,i=0,j=0 ; it_d ; it_d=it_d->next ) { if( it_d == dst ) { dst_bitmap_cur[i] &= ~(1 << j); break; } if( ++j == (8 * sizeof(unsigned int)) ) { i++; j=0; } } } else { LM_DBG("%s call of LB - no destination found\n", (reuse ? "sequential" : "initial")); } /* unlock resources */ for( i=0 ; i<res_cur_n ; i++ ) lock_release(res_cur[i]->lock); /* we're done with load-balancing, now save state */ /* save state - group */ if( group_avp == NULL ) { group_val.n = group; if( add_avp(0, group_avp_name, group_val) != 0 ) { LM_ERR("failed to add GROUP AVP\n"); } } else if( group_val.n != group ) { group_avp->data = (void *)(long)group; } /* save state - flags, save only if they are set */ if( flags_avp == NULL ) { if( flags != LB_FLAGS_DEFAULT ) { flags_val.n = flags; if( add_avp(0, flags_avp_name, flags_val) != 0 ) { LM_ERR("failed to add FLAGS AVP\n"); } } } else if( flags_val.n != flags ) { flags_avp->data = (void *)(long)flags; } /* save state - dst_bitmap mask */ if( (mask_avp!=NULL) && (dst_bitmap_cur!=(unsigned int *)mask_val.s.s) ) { destroy_avp(mask_avp); mask_avp = NULL; } if( mask_avp == NULL ) { mask_val.s.s = (char *)dst_bitmap_cur; mask_val.s.len = bitmap_size_cur * sizeof(unsigned int); if( add_avp(AVP_VAL_STR, mask_avp_name, mask_val) != 0 ) { LM_ERR("failed to add MASK AVP\n"); } } /* save state - dst, save only if we have one */ if( id_avp == NULL ) { if( dst != NULL ) { id_val.n = dst->id; if( add_avp(0, id_avp_name, id_val) != 0 ) { LM_ERR("failed to add ID AVP\n"); } } } else { if( dst != NULL ) { id_avp->data = (void *)(long)dst->id; } else { destroy_avp(id_avp); id_avp = NULL; } } /* save state - res */ /* iterate AVPs once and delete old resources */ destroy_avps(0, res_avp_name, 1 /*all*/); /* add new resources */ for( i=0 ; i<res_cur_n ; i++ ) { res_val.s = res_cur[i]->name; if( add_avp(AVP_VAL_STR, res_avp_name, res_val) != 0 ) LM_ERR("failed to add RES AVP\n"); } /* outcome: set dst uri */ if( (dst != NULL) && (set_dst_uri(req, &dst->uri) != 0) ) { LM_ERR("failed to set duri\n"); return -2; } return dst ? 0 : -2; }
static void resource_event(mrp_msg_t *msg, mrp_res_context_t *cx, int32_t seqno, void **pcursor) { uint32_t rset_id; uint32_t grant, advice; mrp_resproto_state_t state; uint16_t tag; uint16_t type; mrp_msg_value_t value; size_t size; uint32_t resid; const char *resnam; mrp_res_attribute_t attrs[ATTRIBUTE_MAX + 1]; int n_attrs; uint32_t mask, all = 0x0, mandatory = 0x0; uint32_t i; mrp_res_resource_set_t *rset; mrp_log_info("Resource event (request no %u):", seqno); if (!fetch_resource_set_id(msg, pcursor, &rset_id) || !fetch_resource_set_state(msg, pcursor, &state) || !fetch_resource_set_mask(msg, pcursor, 0, &grant) || !fetch_resource_set_mask(msg, pcursor, 1, &advice)) { mrp_log_error("failed to fetch data from message"); goto malformed; } /* Update our "master copy" of the resource set. */ rset = mrp_htbl_lookup(cx->priv->rset_mapping, u_to_p(rset_id)); if (!rset) { mrp_log_error("resource event outside the resource set lifecycle"); goto malformed; } #if 0 switch (state) { case RESPROTO_RELEASE: rset->state = MRP_RES_RESOURCE_LOST; break; case RESPROTO_ACQUIRE: rset->state = MRP_RES_RESOURCE_ACQUIRED; break; } #endif while (mrp_msg_iterate(msg, pcursor, &tag, &type, &value, &size)) { mrp_res_resource_t *res = NULL; if ((tag != RESPROTO_RESOURCE_ID || type != MRP_MSG_FIELD_UINT32) || !fetch_resource_name(msg, pcursor, &resnam)) { mrp_log_error("failed to read resource from message"); goto malformed; } res = get_resource_by_name(rset, resnam); if (!res) { mrp_log_error("resource doesn't exist in resource set"); goto malformed; } resid = value.u32; mrp_log_info("data for '%s': %d", res->name, resid); n_attrs = fetch_attribute_array(msg, pcursor, ATTRIBUTE_MAX + 1, attrs); if (n_attrs < 0) { mrp_log_error("failed to read attributes from message"); goto malformed; } /* TODO: attributes */ } /* go through all resources and see if they have been modified */ for (i = 0; i < rset->priv->num_resources; i++) { mrp_res_resource_t *res = rset->priv->resources[i]; mask = (1UL << res->priv->server_id); all |= mask; if (res->priv->mandatory) mandatory |= mask; if (grant & mask) { res->state = MRP_RES_RESOURCE_ACQUIRED; } #if 1 else { res->state = MRP_RES_RESOURCE_LOST; } #else else if (advice & mask) { res->state = MRP_RES_RESOURCE_AVAILABLE; } else { res->state = MRP_RES_RESOURCE_LOST; } #endif }