Exemplo n.º 1
0
void deliverDispatch(DISPATCH_PTR dispatch)
{
  char *data;
  DATA_MSG_PTR newDataMsg;
  X_IPC_MSG_CLASS_TYPE msg_class;
  CLASS_FORM_PTR classForm;
  
  data = NULL;
  
  dispatchUpdateAndDisplay(AttendingDispatch, dispatch);
  
  if (dispatch->des == GET_S_GLOBAL(x_ipcServerModGlobal)) {
    if (monitorClass(dispatch->msg->msgData->msg_class)) {
      data = dispatch->classData;
    } else {
      data = (char *)x_ipc_dataMsgDecodeMsg(dispatch->msg->msgData->msgFormat, 
				      DISPATCH_MSG_DATA(dispatch),TRUE);
    }
    (*dispatch->hnd->hndProc)(dispatch, data);
    if (dispatch->msg_class == InformClass) {
      dispatchUpdateAndDisplay(HandledDispatch, dispatch);
    }
  } else {
    if (dispatch->hnd->msg != dispatch->msg) {
      /* handler to recieve new message */
      msg_class = ExecHndClass;
      classForm = GET_CLASS_FORMAT(&msg_class);
      if (!classForm)
	X_IPC_ERROR("ERROR: deliverDispatch: missing ExecHndClass class format.");
      
      newDataMsg = 
	x_ipc_dataMsgReplaceClassData(classForm->format,
				(char*)&dispatch->msg->msgData->name,
				dispatch->msgData,
				dispatch->msg->msgData->msgFormat
				);
      
      /* 31-Oct-90: fedor: the x_ipc_dataMsgReplaceClassData routine calls
	 x_ipc_dataMsgFree - this avoids calling it twice and gets the 
	 refs correct. blah! */
      dispatch->msgData = NULL;
      
      dispatchSetMsgData(newDataMsg, dispatch);
    }
    else {
      /* The datamags may already have old class data.
	 Since class data follows message data, this
	 will prevent old class data from being sent. */
      dispatch->msgData->classTotal = 0;
    }
    
    dispatch->msgData->intent = dispatch->hnd->hndData->refId;
    dispatch->msgData->msgRef = dispatch->locId;
    
    (void)x_ipc_dataMsgSend(dispatch->desId, dispatch->msgData);
  }
}
Exemplo n.º 2
0
static void registerClass(X_IPC_MSG_CLASS_TYPE className, char *format)
{
  CONST_FORMAT_PTR form;
  CLASS_FORM_PTR classForm;
  
  form = ParseFormatString(format);
  classForm = GET_CLASS_FORMAT(&className);
  
  if (classForm)
    classForm->format = form;
  else {
    classForm = NEW(CLASS_FORM_TYPE);
    classForm->className = className;
    classForm->format = form;
    
    ADD_CLASS_FORMAT(&className, classForm);
  }
}
Exemplo n.º 3
0
X_IPC_RETURN_VALUE_TYPE x_ipc_sendResponse(X_IPC_REF_PTR ref, MSG_PTR msg,
				   void *resData,
				   X_IPC_MSG_CLASS_TYPE resClass,
				   void *resClassData,
				   int sd)
{
  int32 intent=-1, refId,msgId=-1;
  CONST_FORMAT_PTR format;
  DATA_MSG_PTR dataMsg;
  CLASS_FORM_PTR classForm;
  CONST_FORMAT_PTR classFormat;
  X_IPC_RETURN_STATUS_TYPE result;
  
#ifdef NMP_IPC
  if (ref->responded == TRUE) {
    /* Already responded -- something is wrong! */
    X_IPC_MOD_ERROR2("x_ipc_sendResponse: Already responed to instance %d (%s)\n",
		ref->refId, ref->msg->msgData->name);
  }
#endif

  classFormat = NULL;
  format = NULL;
  
  if (msg) {
#ifndef NMP_IPC
    intent = msg->msgData->refId;
    format = msg->msgData->resFormat;
#else
    /* The only place X_IPC calls this function with "msg" set is in
       fireDemon.  Since IPC doesn't use that, we should be safe using
       "msg" for another reason */
    format = msg->msgData->msgFormat;
    if (!ref->msg) {
      ref->msg = x_ipc_msgFind(ref->name);
      if (ref->msg == NULL) return MsgUndefined;
    }
    if (ref->msg->direct) {
      intent = QUERY_REPLY_INTENT;
      msgId = ref->refId;
    } else {
      intent = -1;
    }

    /* We have to "fool" the receiver of the response into using this
       message for encoding/decoding, rather than the query message.
       Not pretty, but it works.  Depends on the fact that ReplyClass has
       no class data.  Later, rework central so that it knows how to handle
       this case explicitly. */ 
    { int resClass1 = ExecHndClass;
      /* Format for ExecHndClass is "string" -- used to send the message name */
      LOCK_M_MUTEX;
      classForm = GET_CLASS_FORMAT(&resClass1);
      UNLOCK_M_MUTEX;
      classFormat = classForm->format;
      resClassData = (void *)&(msg->msgData->name);
    }
#endif
  } else {
    if (ref) {
      if (!ref->msg) {
	ref->msg = x_ipc_msgFind(ref->name);
	if (ref->msg == NULL) return MsgUndefined;
      }
      if (resData != NULL)
	format = ref->msg->msgData->resFormat;
      msg = ref->msg;
      if (msg->direct){
	intent = QUERY_REPLY_INTENT;
	msgId = ref->refId;
      } else {
	intent = -1;
      }
    }
  }
  
  LOCK_M_MUTEX;
  classForm = GET_CLASS_FORMAT(&resClass);
  UNLOCK_M_MUTEX;

  if (classForm)
    classFormat = classForm->format;
  
  refId = (ref ? ref->refId : NO_REF);
  LOCK_CM_MUTEX;
  dataMsg = x_ipc_dataMsgCreate(GET_C_GLOBAL(parentRefGlobal), intent, 
			  (int32)resClass,
			  refId, msgId, (FORMAT_PTR)format, resData,
			  (FORMAT_PTR)classFormat, resClassData);
  UNLOCK_CM_MUTEX;

  if (dataMsg == NULL) return Failure;
  result = x_ipc_dataMsgSend(sd, dataMsg);

#ifdef NMP_IPC
  if (result == StatOK) {
    if (ref->responded == -1) {
      /* Happening outside of the handler -- nuke the reference */
      x_ipcRefFree(ref);
    } else
      ref->responded = TRUE;
  }
#endif
  
  x_ipc_dataMsgFree(dataMsg);
  
  return (result != StatOK ? Failure : Success);
}
Exemplo n.º 4
0
X_IPC_RETURN_VALUE_TYPE x_ipc_sendMessage(X_IPC_REF_PTR ref, MSG_PTR msg,
					  void *msgData, void *classData,
					  int32 preallocatedRefId)
{
  int32 refId, savedRef, i, sd;
  DATA_MSG_PTR msgDataMsg;
  X_IPC_MSG_CLASS_TYPE msg_class;
  CLASS_FORM_PTR classForm;
  CONST_FORMAT_PTR classFormat;
  X_IPC_RETURN_STATUS_TYPE result;
  DIRECT_MSG_HANDLER_PTR direct;
  CONNECTION_PTR connection;
  
  classFormat = NULL;
  
  if (!msg) {
    X_IPC_MOD_ERROR("ERROR: x_ipc_sendMessage: NULL msg.\n");
  }
  
  if (!x_ipc_isValidServerConnection()) {
    X_IPC_MOD_ERROR("ERROR: Must be connected to the server to send a message");
    return Failure;
  }
  
  /* save the message ref to use in case x_ipc_msgFind triggers 
     a recursive call to x_ipc_sendMessage */
  
  LOCK_CM_MUTEX;
  savedRef = (preallocatedRefId != NO_REF ? preallocatedRefId
	      : x_ipc_nextSendMessageRef());
  
  msg_class = msg->msgData->msg_class;
  classForm = GET_CLASS_FORMAT(&msg_class);
  
  if (classForm)
    classFormat = classForm->format;
  
  refId = (ref ? ref->refId : NO_REF);
  
  /* RTG For now, only do direct if no logging. */
  msgDataMsg = x_ipc_dataMsgCreate(GET_C_GLOBAL(parentRefGlobal), -1,
				   (int32)msg_class, refId, savedRef,
				   msg->msgData->msgFormat, msgData,
				   (FORMAT_PTR)classFormat, classData);
  UNLOCK_CM_MUTEX;
  if (msgDataMsg == NULL) {
    X_IPC_MOD_ERROR1("Unable to send message %s, probably a bad format\n",
		msg->msgData->name);
    return Failure;
  }
  if (!msg->direct || !msg->directList || msg->directList->numHandlers == 0) {
    msgDataMsg->intent = msg->msgData->refId;
    LOCK_CM_MUTEX;
    sd = GET_C_GLOBAL(serverWrite);
    UNLOCK_CM_MUTEX;
    result = x_ipc_dataMsgSend(sd, msgDataMsg);
  } else {
    /* Send in reverse order (to match what happens within central) */
    for (i=msg->directList->numHandlers-1, result=StatOK;
	 i>=0 && result == StatOK; i--) {
      direct = &(msg->directList->handlers[i]);
      if (direct->readSd >= 0) {
	msgDataMsg->intent = direct->intent;
	result = x_ipc_dataMsgSend(direct->writeSd, msgDataMsg);
	if (result == StatError && errno == EPIPE) {
	  fprintf(stderr, "Need to close %d\n", direct->writeSd);
	  LOCK_CM_MUTEX;
	  connection = (CONNECTION_PTR)x_ipc_hashTableFind((void *)&direct->writeSd,
							   GET_C_GLOBAL(moduleConnectionTable));
	  UNLOCK_CM_MUTEX;
	  if (connection) {
	    x_ipcHandleClosedConnection(direct->writeSd, connection);
	    result = StatOK;
	  }
	}
      }
    }
  }

  x_ipc_dataMsgFree(msgDataMsg);
  
  if (result != StatOK) 
    return Failure;
  return Success;
}
Exemplo n.º 5
0
void recvMessageBuild(MODULE_PTR module, DATA_MSG_PTR dataMsg)
{
  char *classData;
  MSG_PTR msg = NULL;
  
  DISPATCH_PTR dispatch;
  X_IPC_MSG_CLASS_TYPE msg_class;
  CLASS_FORM_PTR classForm;
  
  CONST_FORMAT_PTR classFormat = NULL;
  
  if (dataMsg->intent != NO_REF)
    msg = (MSG_PTR)idTableItem(ABS(dataMsg->intent), GET_C_GLOBAL(msgIdTable));
  
  msg_class = (X_IPC_MSG_CLASS_TYPE)dataMsg->classId;
  classForm = GET_CLASS_FORMAT(&msg_class);
  
  if (classForm)
    classFormat = classForm->format;
  
  classData = (char *)x_ipc_dataMsgDecodeClass(classFormat, dataMsg);
  
  if (dataMsg->dispatchRef != NO_REF) {
    dispatch = DISPATCH_FROM_ID(dataMsg->dispatchRef);
  } else {
    dispatch = dispatchAllocate();
    dispatch->msg = msg;
    
    dispatch->org = module;
    dispatch->orgId = module->readSd;
    
    dispatch->refId = dataMsg->msgRef;
    dispatch->pRef = dataMsg->parentRef;
  }
  
  if (dispatch == NULL)
    /* Probably a reply that was not needed */
    return;
  
  if (dataMsg->msgRef == NO_REF)
    dispatchSetResData(dataMsg, dispatch);
  else 
    dispatchSetMsgData(dataMsg, dispatch);
  
  
  /* 22-May-91: fedor: NOTE: class and classData will change if this
     is a previously created dispatch. This may be undesired for
     behavior for a x_ipc_sendResponse call that refers to a previously
     created dispatch. */
  /*  3-Jul-91: reid: Clean up previous class data, 
      except for command class data, which is stored in blockCom */
  if (dispatch->classData && dispatch->msg_class != CommandClass) 
    x_ipc_classDataFree(dispatch->msg_class, dispatch->classData);

  /* RGS 1/11/01: This prevents a reply from being sent when it shouldn't be.
     The problem is that with IPC, one can have a message sent to a query
     handler without expecting a reply (e.g, using a broadcast rather than
     a QueryClass). */
  if (msg_class == ReplyClass && 
      (dispatch->msg_class != QueryClass &&
       dispatch->msg_class != MultiQueryClass)) {
    msg_class = SuccessClass;
  }

  dispatch->msg_class = msg_class;
  dispatch->classData = classData;
  
  recvMessage(dispatch, msg_class, classData);
}
Exemplo n.º 6
0
X_IPC_RETURN_VALUE_TYPE centralSendMessage(X_IPC_REF_PTR ref, MSG_PTR msg,
					 void *msgData, void *classData)
{
  int32 refId, savedRef;
  DATA_MSG_PTR msgDataMsg;
  X_IPC_MSG_CLASS_TYPE msg_class;
  
  CLASS_FORM_PTR classForm;
  
  CONST_FORMAT_PTR classFormat;
  
  classFormat = NULL;
  
  if (!msg) {
    X_IPC_ERROR("ERROR: x_ipc_sendMessage: NULL msg.\n");
  }
  
  /* save the message ref to use in case x_ipc_msgFind triggers 
     a recursive call to x_ipc_sendMessage */
  
  savedRef = x_ipc_nextSendMessageRef();
  
  msg_class = msg->msgData->msg_class;
  
  classForm = GET_CLASS_FORMAT(&msg_class);
  
  if (classForm)
    classFormat = classForm->format;
  
  if (ref) 
    refId = ref->refId;
  else
    refId = NO_REF;
  
  /* 8-Oct-90: fedor:
     parentRefGlobal problem!!! ** it is initialized to -1 in behaviors.c 
     so maybe this will not be a problem */
  
  msgDataMsg = x_ipc_dataMsgCreate(GET_C_GLOBAL(parentRefGlobal),
				   msg->msgData->refId, 
				   (int32)msg_class, refId, savedRef, 
				   msg->msgData->msgFormat,
				   msgData, classFormat, classData);
  
  if (msgDataMsg == NULL) return Failure;
  
  /* RTG - must set datastruct to be null so message does not get decoded 
   * into the same memory location.  We also have to copy the message
   * buffer if it is the same as the original data structure because
   * the original data structure can change, if the message is queued.
   */
  if (msgDataMsg->msgData == msgData) {
    /* Need to copy the data, in case the messages gets queued.  */
    char *newCopy = NULL;
    newCopy = (char *)x_ipcMalloc(msgDataMsg->msgTotal);
    BCOPY(msgDataMsg->msgData, newCopy,msgDataMsg->msgTotal);
    msgDataMsg->msgData = newCopy;
    msgDataMsg->dataStruct = NULL;
  } else 
    msgDataMsg->dataStruct = NULL;

  recvMessageBuild(GET_S_GLOBAL(x_ipcServerModGlobal), msgDataMsg);
  return Success;
}