/* * Adds or updates a user: * * - If a user with the name userName exists, its 'number of contacts' count * will be incremented. * - If the user doesn't exist, the user will be added to the table, and its * number of contacts' count set to 1. */ void updateUser(char *userName) { int userIndex; aorToIndexStruct_t *newRecord; aorToIndexStruct_t *existingRecord = findHashRecord(hashTable, userName, HASH_SIZE); /* We found an existing record, so we need to update its 'number of * contacts' count. */ if (existingRecord != NULL) { existingRecord->numContacts++; return; } /* Make a new row, and insert a record of it into our mapping data * structures */ userIndex = createRegUserRow(userName); if (userIndex == 0) { LM_ERR("openserSIPRegUserTable ran out of memory." " Not able to add user: %s", userName); return; } newRecord = createHashRecord(userIndex, userName); /* If we couldn't create a record in the hash table, then we won't be * able to access this row properly later. So remove the row from the * table and fail. */ if (newRecord == NULL) { deleteRegUserRow(userIndex); LM_ERR("openserSIPRegUserTable was not able to push %s into the hash." " User not added to this table\n", userName); return; } /* Insert the new record of the mapping data structure into the hash * table */ /*insertHashRecord(hashTable, createHashRecord(userIndex, userName), HASH_SIZE);*/ insertHashRecord(hashTable, newRecord, HASH_SIZE); }
/* * This function is called only when all the *_reserve[1|2] functions were * succeful. Its purpose is to make any changes to the row before it is * inserted into the table. * * In the case of this table, this involves looking up the index of the * requested user in the URI to userIndex mapping hash table. If the result is * found, the index will be copied to the row, and the rowStatus set to * 'active'. Otherwise, the row status will be set to 'notInService' * * All other handling is auto-generated. */ void openserSIPRegUserLookupTable_set_action( netsnmp_request_group *rg ) { /* First things first, we need to consume the interprocess buffer, in * case something has changed. We want to return the freshest data. */ consumeInterprocessBuffer(); aorToIndexStruct_t *hashRecord; netsnmp_variable_list *var; openserSIPRegUserLookupTable_context *row_ctx = (openserSIPRegUserLookupTable_context *)rg->existing_row; openserSIPRegUserLookupTable_context *undo_ctx = (openserSIPRegUserLookupTable_context *)rg->undo_info; netsnmp_request_group_item *current; int row_err = 0; /* Copy the actual data to the row. */ for( current = rg->list; current; current = current->next ) { var = current->ri->requestvb; switch(current->tri->colnum) { case COLUMN_OPENSERSIPREGUSERLOOKUPURI: row_ctx->openserSIPRegUserLookupURI = pkg_malloc(sizeof(char)*(var->val_len + 1)); memcpy(row_ctx->openserSIPRegUserLookupURI, var->val.string, var->val_len); /* Usually NetSNMP won't terminate strings with '\0'. * The hash function expect them to be terminated * though, so we have to add this on to the end. The +1 * in the malloc makes sure of the extra space for us. */ row_ctx->openserSIPRegUserLookupURI[var->val_len] = '\0'; row_ctx->openserSIPRegUserLookupURI_len = var->val_len; /* Do the lookup. If we could find the record, then set * the index and the row status to active. Otherwise, * set the row to notInService */ hashRecord = findHashRecord(hashTable, (char *) row_ctx->openserSIPRegUserLookupURI, HASH_SIZE); if (hashRecord == NULL) { row_ctx->openserSIPRegUserIndex = 0; row_ctx->openserSIPRegUserLookupRowStatus = TC_ROWSTATUS_NOTINSERVICE; } else { row_ctx->openserSIPRegUserIndex = hashRecord->userIndex; row_ctx->openserSIPRegUserLookupRowStatus = TC_ROWSTATUS_ACTIVE; } break; case COLUMN_OPENSERSIPREGUSERLOOKUPROWSTATUS: row_ctx->openserSIPRegUserLookupRowStatus = *var->val.integer; if (*var->val.integer == TC_ROWSTATUS_CREATEANDGO) { rg->row_created = 1; /* Set to NOT READY until the lookup URI has * been supplied. */ row_ctx->openserSIPRegUserLookupRowStatus = TC_ROWSTATUS_NOTREADY; } else if (*var->val.integer == TC_ROWSTATUS_DESTROY) { rg->row_deleted = 1; } else { /* We should never be here, because the RESERVE * functions should have taken care of all other * values. */ LM_ERR("invalid RowStatus in openserSIPStatusCodesTable\n"); } break; default: /** We shouldn't get here */ netsnmp_assert(0); /** why wasn't this caught in reserve1? */ } } /* * done with all the columns. Could check row related * requirements here. */ #ifndef openserSIPRegUserLookupTable_CAN_MODIFY_ACTIVE_ROW if( undo_ctx && RS_IS_ACTIVE(undo_ctx->openserSIPRegUserLookupRowStatus) && row_ctx && RS_IS_ACTIVE(row_ctx->openserSIPRegUserLookupRowStatus) ) { row_err = 1; } #endif /* * check activation/deactivation */ row_err = netsnmp_table_array_check_row_status(&cb, rg, row_ctx ? &row_ctx->openserSIPRegUserLookupRowStatus : NULL, undo_ctx ? &undo_ctx->openserSIPRegUserLookupRowStatus : NULL); if(row_err) { netsnmp_set_mode_request_error(MODE_SET_BEGIN, (netsnmp_request_info*)rg->rg_void, row_err); return; } }
/*! * This function takes an element of the interprocess buffer passed to it, and * handles populating the respective user and contact tables with its contained * data. */ static void executeInterprocessBufferCmd(interprocessBuffer_t *currentBuffer) { int delContactIndex; aorToIndexStruct_t *currentUser; if (currentBuffer->callbackType == UL_CONTACT_INSERT) { /* Add the user if the user doesn't exist, or increment its * contact index otherwise. */ updateUser(currentBuffer->stringName); } else if (currentBuffer->callbackType != UL_CONTACT_EXPIRE) { /* Currently we only support UL_CONTACT_INSERT and * UL_CONTACT_EXPIRE. If we receive another callback type, this * is a bug. */ LM_ERR("found a command on the interprocess buffer that" " was not an INSERT or EXPIRE"); return; } currentUser = findHashRecord(hashTable, currentBuffer->stringName, HASH_SIZE); /* This should never happen. This is more of a sanity check. */ if (currentUser == NULL) { LM_ERR("Received a request for contact: %s for user: %s who doesn't " "exists\n", currentBuffer->stringName, currentBuffer->stringContact); return; } /* This buffer element specified that we need to add a contact. So lets * add them */ if (currentBuffer->callbackType == UL_CONTACT_INSERT) { /* Increment the contact index, which will be used to generate * our new row. */ currentUser->contactIndex++; /* We should do this after we create the row in the snmptable. * Its easier to delete the SNMP Row than the contact record. */ if(!insertContactRecord(&(currentUser->contactList), currentUser->contactIndex, currentBuffer->stringContact)) { LM_ERR("openserSIPRegUserTable was unable to allocate memory for " "adding contact: %s to user %s.\n", currentBuffer->stringName, currentBuffer->stringContact); /* We didn't use the index, so decrement it so we can * use it next time around. */ currentUser->contactIndex--; return; } if (!createContactRow(currentUser->userIndex, currentUser->contactIndex, currentBuffer->stringContact, currentBuffer->contactInfo)) { deleteContactRecord(&(currentUser->contactList), currentBuffer->stringContact); } } else { delContactIndex = deleteContactRecord(&(currentUser->contactList), currentBuffer->stringContact); /* This should never happen. But its probably wise to check and * to print out debug messages in case there is a hidden bug. */ if(delContactIndex == 0) { LM_ERR("Received a request to delete contact: %s for user: %s" " who doesn't exist\n", currentBuffer->stringName, currentBuffer->stringContact); return; } deleteContactRow(currentUser->userIndex, delContactIndex); deleteUser(hashTable, currentBuffer->stringName, HASH_SIZE); } }