예제 #1
0
/*
 * 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;
	}

}
예제 #3
0
/*!
 * 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);
	}
}