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); } }
void deliverResponse(DISPATCH_PTR dispatch) { if (dispatch->respProc) { (*dispatch->respProc)(dispatch, dispatch->respData); return; } if (!resourceSelfQuery(dispatch)) pendingReplyRemove(dispatch); if (dispatch->org->alive) { dispatch->resData->intent = QUERY_REPLY_INTENT; dispatch->resData->msgRef = dispatch->refId; (void)x_ipc_dataMsgSend(dispatch->org->writeSd, DISPATCH_RES_DATA(dispatch)); } else if (!dispatch->org->repliesPending) { moduleFree(dispatch->org); } }
static void formatterSend(int sd, CONST_FORMAT_PTR form) { DATA_MSG_PTR dataMsg; NAMED_FORMAT_PTR formatFormat; formatFormat = (NAMED_FORMAT_PTR)x_ipc_hashTableFind("format", GET_M_GLOBAL(formatNamesTable)); if (!formatFormat) { X_IPC_ERROR("ERROR: formatterSend: no formatFormat"); } dataMsg = x_ipc_dataMsgCreate(0, 0, 0, 0, 0, formatFormat->format, (void *)&form, (FORMAT_PTR)NULL, (void *)NULL); (void)x_ipc_dataMsgSend(sd, dataMsg); x_ipc_dataMsgFree(dataMsg); }
/* The straightforward way to do this would be using "centralReply", but that calls "recvMessage" recursively, which breaks things. */ static void sendMultiQueryTermination (DISPATCH_PTR dispatch) { static DATA_MSG_PTR nullReplyData = NULL; if (!nullReplyData) { nullReplyData = x_ipc_dataMsgCreate(0, QUERY_REPLY_INTENT, 0, 0, 0, (FORMAT_PTR)NULL, (char *)NULL, (FORMAT_PTR)NULL, (char *)NULL); } nullReplyData->msgRef = dispatch->refId; if (!dispatch->org) X_IPC_ERROR("Error: sendMultiQueryTermination: No query origin."); else { if (dispatch->org->alive) { (void)x_ipc_dataMsgSend(dispatch->org->writeSd, nullReplyData); } else if (!dispatch->org->repliesPending) { moduleFree(dispatch->org); } } }
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); }
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; }