mms_client.c revision cee0fb94c0d4227de0a00efc162fb2739844b641
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <mms.h>
#include <mgmt_mms.h>
/* Only first call to mms_init or mms_ainit */
/* will create a mms_trace file if called for */
char mms_empty_string[] = "empty";
char *mms_empty_message = "No loctext message found\n";
char *mms_api[] = {
"Unconfigured",
"Asynchronous",
"Synchronous",
NULL};
char *mms_state[] = {
"Unconfigured",
"Configured",
"Failure",
"Shutdown",
NULL};
/*
* mms_free_rsp()
*
* Parameters:
* - rsp Pointer to a response returned from one of
* routines that return a command response or
* the response sent to a callback routine.
*
* This function is used by a client to free unneeded responses to commands.
* list elements.
*
* Return Values:
* None
*
*/
void
mms_free_rsp(void *rsp)
{
"list element memory");
} else {
"NULL, no memory to free");
}
}
/*
* mms_handle_err_rsp()
*
* Parameters:
* - response The error response to process
* - class The class contained in the response
* - code The code contained in the response
* - msg The internationalized version of the error message
* This message needs to be freed by the client once
* it is done with it.
*
* This function takes an error response and processes on behalf of the
* the client.
*
* Return Values:
* - MMS_API_NOT_ERR_RSP if response is not an error response
* - MMS_API_ERROR if unable to obtain error class and code
* - MMS_API_OK if processing completed correctly
*
*/
int
{
return (MMS_API_NOT_ERR_RSP);
}
NULL);
}
return (MMS_API_OK);
return (MMS_API_ERROR);
}
/*
* mms_hello()
*
* Parameters:
* - session Session structure to to use to connect to MMS.
* - host The hostname of where MM is running.
* - port The port where MM is running.
* - app Name of client's application name to use in
* HELLO command.
* - ai Name of client's application instance to use in
* HELLO command.
* - tag This is an optional parameter that a client can
* specify that will tag the session with this value.
* If no tag is to be used, use NULL.
* - cli_pass Client's password to use in HELLO command.
* - mm_pass Optional, expected password in MMS_WELCOME response,
* set to null for no password validation.
* - ssl_data SSL connection data is required for secure MM,
* set to null for no SSL connection.
*
* This function fills in the network structure with the client's
* specific information to use in the HELLO command that is to
* be sent to MMS.
* If the connection is an async connection, it will start the writer and
* reader threads after the connection is established.
*
* Return Values:
* MMS_API_OK If connection was made successfully.
* ! MMS_API_OK The code relevant to the internal processing error
* that was encountered. If the client has registered
* a logging routine for the API, a message will be
* sent to that routine.
*
*/
int
{
int rc;
return (rc);
}
/*
* mms_hello_net()
*
* Parameters:
* - session Session structure to to use to connect to MMS.
* - net MMS network configuration where the MMS MM is located.
* - tag This is an optional parameter that a client can
* specify that will tag the session with this value.
* If no tag is to be used, use NULL.
* - ssl_data SSL connection data is required for secure MM,
* set to null for no SSL connection.
*
* This function uses the network structure with the client's
* specific information to use in the HELLO command that is to
* be sent to MMS.
* If the connection is an async connection, it will start the writer and
* reader threads after the connection is established.
*
* Return Values:
* MMS_API_OK If connection was made successfully.
* ! MMS_API_OK The code relevant to the internal processing error
* that was encountered. If the client has registered
* a logging routine for the API, a message will be
* sent to that routine.
*
*/
int
{
int rc;
int err;
return (err);
}
/* Start reader thread */
mms_api_reader, (void *)sp)) != 0) {
}
/* Wait until reader thread gets starts */
}
&sp->mms_acc_mutex)) != 0) {
"on reader start condition variable, errno "
}
}
}
}
return (MMS_API_OK);
}
/*
* mms_sess_create
*
* Allocate and initialize a session structure.
*/
{
int rc;
"mms_sess_create: Malloc of memory for a new "
return (NULL);
}
/*
* Create lists for the command responses, registered events,
* and events received.
*/
/*
* Initialize a mutex used to track the number of outstanding
* client threads with pending MM requests.
*/
}
}
/*
* Initialize a mutex to allow only one command to be
* sent to MMS until a accept response is received.
*/
}
/*
* Create mutex and condition variable to coordinate handling of
* waiting on accept response.
*/
}
}
/*
* Initialize a mutex used to manage the pending commands.
*/
}
/*
* Create mutex and condition variable to coordinate handling of
* final responses between a reader thread and a thread waiting on
* final response.
*/
}
"list condition variable failed with errno - %s",
}
/*
* Initialize a mutex and condition variable which will be used to
* prevent more than one begin-end sequence being sent to the MM.
*/
}
}
/*
* Create mutex to allow only one thread to write to the
* socket at a time.
*/
}
/*
* Create mutex to allow only one thread to become the socket reader.
*/
}
/*
* Initialize an event manager mutex and condition variable.
*/
}
}
}
PTHREAD_CREATE_DETACHED)) != 0) {
}
sp->mms_thrd_cnt = 0;
return (sp);
}
/*
* mms_sess_free
*
* Free all resources used to manage a session.
*/
void
{
int rc;
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
/*
* mms_mm_shutdown
*
* Send a shutdown request to the MM.
*/
void
{
void *rsp;
char cmd_str[128];
int rc;
if (force) {
return;
}
"goodbye task[\"api_goodbye\"];");
return;
}
switch (mms_rsp_type(rsp)) {
case MMS_API_RSP_UNACC:
"response to goodbye command");
break;
case MMS_API_RSP_FINAL:
"response to goodbye command");
break;
case MMS_API_RSP_FINAL_ERR:
"response to goodbye command");
break;
case MMS_API_RSP_FINAL_CANC:
"response to goodbye command");
break;
default:
"response to goodbye command");
break;
}
}
/*
* mms_shutdown
*
* Shutdown all activity for a session.
*/
void
{
int rc;
/*
* Send a shutdown command to the MM.
*/
/*
* Set state of API session to shutdown.
*/
/*
* Close socket to MM.
*/
"outstanding api threads to shutdown, current count - %d",
sp->mms_thrd_cnt);
/*
* Broadcast to wake any client threads in a condition wait.
*/
}
}
}
}
}
}
}
}
}
/*
* Check to see if any client threads are still outstanding.
*/
}
if (sp->mms_thrd_cnt != 0) {
"wait period expired waiting for all "
"client threads to exit, forcing shutdown");
else
"wait on thread condition variable, "
} else {
"mms_shutdown: all outstanding client "
"threads have exited, connection to MM closed");
}
} else {
"mms_shutdown: There are no outstanding client "
"threads currently running, connection to MM closed");
}
}
/*
* Clean the event lists.
*/
}
}
}
/*
* Clean the response list.
*/
}
}
}
/*
* Clean the command list.
*/
}
}
}
}
/*
* mms_init()
*
* Parameters:
* - session If init is successful, returns the pointer to the new
* session structure that the client uses to
* communicate with MMS. If an error occurs it is set
* to NULL;
* - version Set to the version that the API was built with.
* The client will use this to determine if it is
* compatible with the MMS API.
*
* This function initializes the mutexs, condition variables, lists,
* necessary for a client to communicate with MMS in a sync mode.
*
* Return Values:
* MMS_API_OK If a new sessions was successfully created.
* ! MMS_API_OK The code relevant to the internal processing error
* that was encountered. If the client has registered
* a logging routine for the API, a message will be
* sent to that routine.
*
*/
int
{
return (MMS_INVALID_REQ);
}
return (MMS_MALLOC_ERROR);
}
"to MMS complete");
return (MMS_API_OK);
}
/*
* mms_ainit()
*
* Parameters:
* - session If init is successful, returns a pointer to the new
* session structure that the client uses to
* communicate with MMS. If an error occurs it is set
* to NULL;
* - version Set to the version the API was built with.
* The client will use this to determine if it is
* compatible with the MMS API.
* - err_callbk The routine that is to be called when the reader
* detects an internal processing error and is ready to
* exit. This function is called to notify the client
* that a internal processing error has occurred and
* the api is no longer is a stable state. This routine
* is also called when reader exits because the api
* has been terminated by the client.
* - ev_callbk The routine that is to be called when an event is
* received.
*
* This function initializes the mutexs, condition variables, lists,
* necessary for a client to communicate with MMS in a async mode.
*
* Return Values:
* MMS_API_OK If a new sessions was successfully created
* ! MMS_API_OK The code relevant to the internal processing error
* that was encountered. If the client has registered
* a logging routine for the API, a message will be
* sent to that routine.
*
*/
int
{
return (MMS_INVALID_REQ);
}
return (MMS_MALLOC_ERROR);
}
/*
* Set callback function to process events.
*/
if (ev_callbk) {
} else {
}
/*
* Set callback function in case reader thread needs to
* shutdown due to internal processing.
*/
if (err_callbk) {
} else {
}
"connection to MMS complete");
return (MMS_API_OK);
}
/*
* mms_goodbye()
*
* Parameters:
* - session The session that is to be closed
* - force 0 - indicates graceful shutdown
* 1 - indicates an immediate shutdown
*
* This function closes a synchronouse session that a client has open with MMS.
*
* Return Values:
* MMS_API_OK If session was closed successfully
* ! MMS_API_OK The code relevant to the internal processing error
* that was encountered. If the client has registered
* a logging routine for the API, a message will be
* sent to that routine.
*
*/
int
{
"NULL, unable to close session");
return (MMS_INVALID_REQ);
}
"on a session which is not an sync session");
return (MMS_WRONG_API_MODE);
}
/*
* Shutdown the session.
*/
/*
* Free all resources used to manage the session.
*/
return (MMS_API_OK);
}
/*
* mms_agoodbye()
*
* Parameters:
* - session The session that is to be closed
* - force 0 - indicates graceful shutdown
* 1 - indicates an immediate shutdown
*
* This function closes a asynchronous session that a client has open with mms
*
* Return Values:
* MMS_API_OK If session was closed successfully.
* ! MMS_API_OK An error code indicating the error encountered.
*
*/
int
{
"NULL, unable to close session");
return (MMS_INVALID_REQ);
}
"on a session which is not an async session");
return (MMS_WRONG_API_MODE);
}
/*
* Shutdown the session.
*/
/*
* Free all resources used to manage the session.
*/
return (MMS_API_OK);
}
/*
* mms_send_cmd()
*
* Parameters:
* - session The structure used to access the socket to MMS.
* - cmd The MMP cmd to be sent to MMS.
* - rsp The response from MMS to the cmd. This is actually a
* mms_rsp_ele_t structure. When the client is
* done with the response, they need to call
* mms_free_rsp() to free up the strucutes memory.
*
* This function sends MMP commands to MMS and waits for a response to them.
* It returns in rsp a MMS response structure. The client will then use
* other MMS API commands to obtain the information from the response, thus
* the client does not need to know the actual format of the response
* actually pull the response apart in order to determine what it needs from
* structure. If a processing error has occurred within the MMS API, this
* routine will return a error response and return a value indicating what
* processing error occurred.
*
* Return Values:
* MMS_API_OK If it received a vaild response from MMS
* ! MMS_API_OK The code relevant to the internal processing error
* that was encountered. If the client has registered
* a logging routine for the API, a message will be
* sent to that routine.
*
*/
int
{
char *tid;
int rc;
" for the command");
return (MMS_INVALID_REQ);
}
cmd);
"for the response");
return (MMS_INVALID_REQ);
}
"to NULL, unable to send new command:\n%s", cmd);
return (MMS_INVALID_REQ);
}
"error, unable to send new command:\n%s", cmd);
return (sp->mms_api_errcode);
}
/*
* Extract the command type and task id from the command.
*/
if (rc != MMS_API_OK) {
return (rc);
}
/*
* The begin-end command sequence cannot be issued synchronously.
*/
return (MMS_INVALID_REQ);
}
/*
* Create and queue a command element to manage the command.
*/
}
/*
* Send the command and wait for the accept.
*/
/*
* Return an error if the command could not be sent or
* was not accepted.
*/
if (rc != MMS_API_OK) {
return (rc);
}
return (rc);
}
/*
* Wait for the final response.
*/
if (rc != MMS_API_OK) {
if (rc != MMS_API_SHUTDOWN)
"response failed %d, %s for command:\n%s", rc,
return (rc);
}
return (MMS_API_OK);
}
/*
* mms_read_response()
*
* Parameters:
* - session The structure used to communicate with MMS.
* - tid The task id for the command that client is waiting
* for additional responses for.
* - rsp Will contain the next response for the command with
* taskid.
*
* This function obtains secondary responses to commands that have been sent
* to MMS. The function should only be called if the mms_send_cmd()
* function received a "intermediate" response or a prior call to this
* function received a "intermediate" response.
*
* Return Values:
* MMS_API_OK If a response from MMS was received without any
* internal processing errors.
* ! MMS_API_OK The code relevant to the internal processing error
* that was encountered. If the client has registered
* a logging routine for the API, a message will be
* sent to that routine.
*
*/
int
{
int rc;
"response");
return (MMS_INVALID_REQ);
}
"set to NULL, unable to obtain a response for command "
"with taskid %s", tid);
return (MMS_INVALID_REQ);
}
"state of error, unable to obtain a response for command "
"with taskid %s", tid);
return (sp->mms_api_errcode);
}
if (rc != MMS_API_OK) {
if (rc != MMS_API_SHUTDOWN) {
"response for command with taskid %s from MMS "
}
return (rc);
}
return (MMS_API_OK);
}
/*
* mms_send_acmd()
*
* Parameters:
* - sp The structure used to access the socket to MMS.
* - tid The task id of the MMP command to be sent to MMS.
* - cmd The MMP cmd to be sent to MMS.
* - callbk The routine that is to be called when the reader
* receives a final response for the command.
* - callbk_param A user specified parameter to send to the callbk
* function when the final response is received.
*
* This function sends MMP commands to MMS and does not wait for any type
* of response from MMS before returning to the caller of this function.
* It just adds the command to the outstanding command list and the send
* command list and returns.
*
* Return Values:
* MMS_API_OK If function completed correctly.
* ! MMS_API_OK The code relevant to the internal processing error
* that was encountered. If the client has registered
* a logging routine for the API, a message will be
* sent to that routine.
*
*/
int
void *callbk_param)
{
char *tid;
int rc;
"specified for command");
return (MMS_INVALID_REQ);
}
cmd);
"to NULL, unable to send new comand:\n%s", cmd);
return (MMS_INVALID_REQ);
}
"for callback function");
return (MMS_INVALID_REQ);
}
"of error, unable to send new command:\n%s", cmd);
return (sp->mms_api_errcode);
}
/*
* MM connection must have been initialized in asynchronous mode.
*/
"API connection in ASYNC mode, though it is configured for "
return (MMS_WRONG_API_MODE);
}
/*
* Extract the command type and task id from the command.
*/
if (rc != MMS_API_OK) {
return (rc);
}
/*
* Create and add the command to the command list for this
* session.
*/
/*
* Send the command and wait for an accept.
*/
/*
* Return an error if the command could not be sent or
* was not accepted.
*/
if (rc != MMS_API_OK) {
return (rc);
}
"%s accepted", tid);
return (MMS_API_OK);
}
/*
* mms_read_event()
*
* Parameters:
* - session Connection to MMS to use.
* - event The generic response structure used to store the
* event to be processed by the client.
*
* This function obtains events from MMS. When MMS has an event to send
* to a client, it sends it over the session socket. This routine pulls the
* event off the socket and then returns it to the client. A client needs to
* call mms_free_rsp() to free the memory associated with the event structure
* that is returned.
*
* Return Values:
* MMS_API_OK If it was able to obtain a event successfully.
* ! MMS_API_OK The code relevant to the internal processing error
* that was encountered.
*
*/
int
{
int rc;
return (MMS_INVALID_REQ);
}
/*
* Wait for an event.
*/
if (rc != MMS_API_OK) {
if (rc != MMS_API_SHUTDOWN) {
"mms_read_event: obtaining new event "
"failed, error code - %d, %s", rc,
}
return (rc);
}
return (MMS_API_OK);
}
/*
* mms_get_attr_aux()
*
* Parameters:
* - top The top of the list being searched
* - start The starting point to search from in the list
* - str The string to search for
* - type The type of attribute to search for
* receives a final response for the command.
* - self Indicates if start should be searched.
*
* This function calls itself recursivily looking for str in the list
* top starting at the start location.
*
* Return Values:
* Returns a pointer to the node in the list that matches str and type
* or it returns NULL if the list is exhausted without finding str.
*
*/
static mms_par_node_t *
int self)
{
return (NULL);
}
/* Start from the start node */
if (self == 1) {
/* found a matching node */
return (start);
}
}
/* Already did self check, don't do it again */
self = 0;
}
/* Have a new start node, do self check on this one */
self = 1;
}
/* found a matching node */
return (result);
}
/* skip value of name value pair */
}
/* Do self check from now on */
self = 1;
}
/* Can't find a matching node. */
return (NULL);
}
/*
* mms_get_attribute()
*
* Parameters:
* - rsp The response that is to be processed
* - name The name of the attribute to scan the response for.
* - prev Maintains the location of how far the scan has been
* done between calls. The client sets this to NULL
* on the initial call to this routine and then the
* routine updates it to keep track of where it is in
* the response.
*
* This function takes a response that has a report in namevalue form
* and looks through it for the name attribute. It returns the value
* associated with the name when it finds one.
*
* Return Values:
* value of name If a name attribute was found it returns the value
* associated with the attribute.
* NULL If no name attribute was found.
*
*/
char *
{
int self = 1;
return (NULL);
}
return (NULL);
}
start = clause_top;
} else {
self = 0;
}
"mms_get_attribute: No more "
"text clause found");
continue;
}
start = clause_top;
} else {
start = clause_top;
continue;
}
self = 1;
break;
}
"mms_get_attribute: Next value for "
return (mms_pn_token(value));
}
}
return (NULL);
}