//Send event from repeater to outside world by forking an event-sending process //If event-sending process is running, check if it finished and clean up void handleRepeaterEvents(void) { pid_t pid; if (0 == eventProc) { //Event posting process is not running, create one if events in fifo if (!isFifoEmpty()) { //fork doEvent pid = fork(); if (-1 == pid) { //fork failed. This is so unfair. Exit and blame Linus ;-) fatal(LEVEL_0, "handleRepeaterEvents(): fork() failed. Linus, this is *so* unfair\n"); } else if (0 == pid) { //child code debug(LEVEL_3, "handleRepeaterEvents(): in child process, starting doEventWork()\n"); exit(doEventWork()); } else { //parent code //Store child pid to variable eventProc so we can //properly clean up after child has exited eventProc = pid; //Clean parent process' fifo clearFifo(); } } } else { //Event-sending process is running, check if run has ended cleanUpAfterEventProc(); } }
// ************************ USB interrupt event processing ************************* void usbirqHookProcessEvents(void) { T1CNTL=0; if (usbirqData.eventMask & USBIRQ_EVENT_EP5IN){ if (isFifoEmpty()==0){ struct UsbISR * msg = (struct UsbISR *)osal_msg_allocate(sizeof(struct UsbISR) ); msg->msg.event = EVENT_USB_ISR; msg->isr = eventSendFifo; osal_msg_send(zusbTaskId, (uint8 *)msg); } } if (usbirqData.eventMask & USBIRQ_EVENT_EP2OUT){ uint8 oldEndpoint = USBFW_GET_SELECTED_ENDPOINT(); USBFW_SELECT_ENDPOINT(2); uint8 length = USBFW_GET_OUT_ENDPOINT_COUNT_LOW(); if (length > MAX_DATE_SIZE_2){ length = MAX_DATE_SIZE_2; } if (length) { struct UsbISR * msg =NULL; uint8 code = USBF2; switch( code){ case ENABLE_INFO_MESSAGE: usbOn=1; break; case REQ_RESET: msg = (struct UsbISR *)osal_msg_allocate(sizeof(struct UsbISR) ); msg->msg.event = EVENT_USB_ISR; msg->isr = eventReset; break; case REQ_BIND_TABLE: { uint8 addr[2]; addr[0] = USBF2; addr[1] = USBF2; struct BindTableRequestMsg * msgReq = (struct BindTableRequestMsg *)osal_msg_allocate(sizeof(struct BindTableRequestMsg) ); msg = &(msgReq->isr); msg->isr = eventBindReq; msg->msg.event = EVENT_USB_ISR; msgReq->afAddrType.addrMode = Addr16Bit; msgReq->afAddrType.addr.shortAddr = *(uint16 *)(addr); } break; case REQ_ACTIVE_EP:{ struct ReqActiveEndpointsEvent * msgEP = (struct ReqActiveEndpointsEvent *)osal_msg_allocate(sizeof(struct ReqActiveEndpointsEvent) ); msg = &(msgEP->isr); msg->isr = eventActiveEP; msg->msg.event = EVENT_USB_ISR; msgEP->data[0] = USBF2; msgEP->data[1] = USBF2; } break; case REQ_ADD_BIND_TABLE_ENTRY: msg = createMsgForBind(); msg->isr = eventBindRequest; break; case REQ_REMOVE_BIND_TABLE_ENTRY: msg = createMsgForBind(); msg->isr = eventUnbindRequest; break; case NODE_POWER_REQUEST:{ struct ReqPowerNodeMsg * msgReq =(struct ReqPowerNodeMsg *)osal_msg_allocate(sizeof(struct ReqPowerNodeMsg) ); msg = &(msgReq->isr); msg->isr = eventReqPowerNode; msg->msg.event = EVENT_USB_ISR; msgReq->data[0] = USBF2; msgReq->data[1] = USBF2; } break; case REQ_IEEE_ADDRESS:{ struct ReqIeeeAddrMsg * msgReq = (struct ReqIeeeAddrMsg *)osal_msg_allocate(sizeof(struct ReqIeeeAddrMsg) ); msg = &(msgReq->isr); msg->isr = eventReqIeeeAddr; msg->msg.event = EVENT_USB_ISR; msgReq->data[0] = USBF2; msgReq->data[1] = USBF2; msgReq->requestType = USBF2; msgReq->startIndex = USBF2; break; } case WRITE_ATTRIBUTE_VALUE:{ struct WriteAttributeValueUsbMsg usbMsg; uint8 * data = (uint8 *)(&usbMsg); uint8 i; for(i=0; i < sizeof(struct WriteAttributeValueUsbMsg); i++){ *data = USBF2; data++; } struct WriteAttributeValueMsg * msgCmd = (struct WriteAttributeValueMsg *)osal_msg_allocate(sizeof(struct WriteAttributeValueMsg) +sizeof(zclWriteRec_t) + usbMsg.dataValueLen ); msg = &(msgCmd->isr); msg->isr = eventWriteValue; msg->msg.event = EVENT_USB_ISR; msgCmd->afAddrType.addrMode=afAddr16Bit; msgCmd->afAddrType.addr.shortAddr=usbMsg.nwkAddr; msgCmd->afAddrType.endPoint=usbMsg.endpoint; msgCmd->cluster = usbMsg.cluster; msgCmd->writeCmd.numAttr=1; msgCmd->writeCmd.attrList->attrID = usbMsg.attributeId; msgCmd->writeCmd.attrList->dataType=usbMsg.dataType; data = ((uint8 *)msgCmd) + sizeof(struct WriteAttributeValueMsg) +sizeof(zclWriteRec_t); msgCmd->writeCmd.attrList->attrData = data; for(i=0; i < usbMsg.dataValueLen; i++){ *data = USBF2; data++; } } break; case SEND_CMD:{ struct SendCmdUsbMsg usbMsg; uint8 * data = (uint8 *)(&usbMsg); uint8 i; for(i=0; i < sizeof(struct SendCmdUsbMsg); i++){ *data = USBF2; data++; } struct SendCmdMsg * msgCmd = (struct SendCmdMsg *)osal_msg_allocate(sizeof(struct SendCmdMsg) +usbMsg.dataLen ); msg = &(msgCmd->isr); msg->isr = eventSendCmd; msg->msg.event = EVENT_USB_ISR; msgCmd->cluster =usbMsg.cluster; msgCmd->cmdClusterId = usbMsg.cmdClusterId; msgCmd->afAddrType.addr.shortAddr= usbMsg.nwkAddr; msgCmd->afAddrType.addrMode = afAddr16Bit; msgCmd->afAddrType.endPoint = usbMsg.endpoint; msgCmd->dataLen = usbMsg.dataLen; data = (uint8 *)(msgCmd->data); for(i=0; i < usbMsg.dataLen; i++){ *data = USBF2; data++; } } break; case REQ_ATTRIBUTE_VALUES: { struct ReqAttributeValueMsg attr; uint8 * data = (uint8 *)(&attr); uint8 i; for(i=0; i < sizeof(struct ReqAttributeValueMsg); i++){ *data = USBF2; data++; } struct ReqAttributeMsg * msgAttr = (struct ReqAttributeMsg *)osal_msg_allocate(sizeof(struct ReqAttributeMsg) +attr.numAttributes* sizeof(uint16) ); msg = &(msgAttr->isr); msg->isr = attributeValue; msg->msg.event = EVENT_USB_ISR; msgAttr->afAddrType.addr.shortAddr = attr.nwkAddr; msgAttr->afAddrType.addrMode = afAddr16Bit; msgAttr->afAddrType.endPoint = attr.endpoint; msgAttr->numAttr = attr.numAttributes; data = (uint8 *)&msgAttr->attrID; for (uint8 i=0; i < attr.numAttributes; i++){ *data = USBF2; data++; *data = USBF2; data++; } msgAttr->cluster = attr.cluster; osal_msg_send(zusbTaskId, (uint8 *)msg); break; } case REQ_DEVICE_INFO:{ struct ReqDeviceInformationEvent * msgEP = (struct ReqDeviceInformationEvent *)osal_msg_allocate(sizeof(struct ReqDeviceInformationEvent) ); msg = &(msgEP->isr); msg->isr = eventDeviceInfo; msg->msg.event = EVENT_USB_ISR; msgEP->data[0] = USBF2; msgEP->data[1] = USBF2; } break; } if (msg != NULL) { uint8 low = T1CNTL; uint8 hi = T1CNTH; msg->time=BUILD_UINT16(low,hi); osal_msg_send(zusbTaskId, (uint8 *)msg); } /*uint8 __generic *pTemp = rxData; do { *(pTemp++) = USBF2; } while (--length);*/ } USBFW_ARM_OUT_ENDPOINT(); USBFW_SELECT_ENDPOINT(oldEndpoint); } }
//For each event in FIFO, build a message line for repeatereventlistener and send it //This procedure accesses eventFifo, but there is no need for synchronization (with main repeater process) //because we got our own copy of memory when kernel started us static int doEventWork(void) { connectionEvent *connEv; sessionEvent *sessEv; startEndEvent *seEv; int eventNum; repeaterEvent ev; int msgLen; #ifdef EVENTS_USE_LISTENER int connection; char eventMessageToListener[MAX_EVENT_MSG_LEN]; char eventListenerIp[MAX_IP_LEN]; if (strcmp(eventHandlerType,"eventlistener") == 0) { connection = openConnectionToEventListener(eventListenerHost, eventListenerPort, eventListenerIp, MAX_IP_LEN); if (-1 != connection) { while(!isFifoEmpty()) { ev = eventFifo[fifoTailInd]; itemsInFifo--; fifoTailInd = advanceFifoIndex(fifoTailInd); eventNum = ev.eventNum; switch (eventNum) { case VIEWER_CONNECT: case VIEWER_DISCONNECT: case SERVER_CONNECT: case SERVER_DISCONNECT: connEv = (connectionEvent *) ev.extraInfo; msgLen = snprintf(eventMessageToListener, MAX_EVENT_MSG_LEN, "EvMsgVer:%d,EvNum:%d,Time:%ld,Pid:%d,TblInd:%d,Code:%ld,Mode:%d,Ip:%d.%d.%d.%d\n", REP_EVENT_VERSION, eventNum, ev.timeStamp, ev.repeaterProcessId, connEv -> tableIndex, connEv -> code, connEv -> connMode, connEv->peerIp.a,connEv->peerIp.b,connEv->peerIp.c,connEv->peerIp.d); break; case VIEWER_SERVER_SESSION_START: case VIEWER_SERVER_SESSION_END: sessEv = (sessionEvent *) ev.extraInfo; msgLen = snprintf(eventMessageToListener, MAX_EVENT_MSG_LEN, "EvMsgVer:%d,EvNum:%d,Time:%ld,Pid:%d,SvrTblInd:%d,VwrTblInd:%d," "Code:%ld,Mode:%d,SvrIp:%d.%d.%d.%d,VwrIp:%d.%d.%d.%d\n", REP_EVENT_VERSION, eventNum, ev.timeStamp, ev.repeaterProcessId, sessEv -> serverTableIndex, sessEv -> viewerTableIndex, sessEv -> code, sessEv -> connMode, sessEv->serverIp.a, sessEv->serverIp.b, sessEv->serverIp.c, sessEv->serverIp.d, sessEv->viewerIp.a, sessEv->viewerIp.b, sessEv->viewerIp.c, sessEv->viewerIp.d); break; case REPEATER_STARTUP: case REPEATER_SHUTDOWN: case REPEATER_HEARTBEAT: seEv = (startEndEvent *) ev.extraInfo; msgLen = snprintf(eventMessageToListener, MAX_EVENT_MSG_LEN, "EvMsgVer:%d,EvNum:%d,Time:%ld,Pid:%d,MaxSessions:%d\n", REP_EVENT_VERSION, eventNum, ev.timeStamp, ev.repeaterProcessId, seEv -> maxSessions); break; default: msgLen = 0; strlcpy(eventMessageToListener, "\n", MAX_EVENT_MSG_LEN); break; } if (msgLen > 0) { writeExact(connection, eventMessageToListener, strlen(eventMessageToListener), TIMEOUT_5SECS); debug(LEVEL_3, "%s", eventMessageToListener); } } close(connection); } } #endif //EVENTS_USE_LISTENER #ifdef EVENTS_USE_MYSQL char eventMessageSQL[MAX_EVENT_SQL_LEN]; debug(LEVEL_3,"Event handler type: %s, length: %i, strcmp: %i\n",eventHandlerType,strlen(eventHandlerType),strcmp(eventHandlerType,"mysql")); if (strcmp(eventHandlerType,"mysql") == 0) { int status = 0; MYSQL mysql; mysql_init(&mysql); if (!mysql_real_connect(&mysql,mysqlHost,mysqlUser,mysqlPass,mysqlDb,0,NULL,0)) { debug(LEVEL_1, "Failed to connect to database (%s:%i, %s): Error: %s\n",mysqlHost,mysqlPort,mysqlDb,mysql_error(&mysql)); } else { debug(LEVEL_3,"Connected to MySQL Database\n"); while(!isFifoEmpty()) { ev = eventFifo[fifoTailInd]; itemsInFifo--; fifoTailInd = advanceFifoIndex(fifoTailInd); eventNum = ev.eventNum; char cuid_str[36]; char puid_str[36]; char cuid_str2[36]; memset(cuid_str, 0, 36); memset(puid_str, 0, 36); memset(cuid_str2, 0, 36); switch (eventNum) { case VIEWER_CONNECT: status = 1; connEv = (connectionEvent *) ev.extraInfo; uuid_unparse(connEv->uid,cuid_str); uuid_unparse(process_uid,puid_str); msgLen = snprintf(eventMessageSQL, MAX_EVENT_SQL_LEN, "INSERT INTO viewers (uid,repeater_uid,lasttime,status,table_index,code,mode,ip) VALUES ('%s','%s',%ld,%d,%d,%ld,%d,'%d.%d.%d.%d');\n", cuid_str,puid_str, ev.timeStamp, status,connEv->tableIndex,connEv->code,connEv->connMode, connEv->peerIp.a,connEv->peerIp.b,connEv->peerIp.c,connEv->peerIp.d); break; case VIEWER_DISCONNECT: status = 0; connEv = (connectionEvent *) ev.extraInfo; uuid_unparse(connEv->uid,cuid_str); msgLen = snprintf(eventMessageSQL, MAX_EVENT_SQL_LEN, "UPDATE viewers SET lasttime = %ld,status = %d WHERE uid = '%s';\n", ev.timeStamp, status,cuid_str); break; case SERVER_CONNECT: status = 1; connEv = (connectionEvent *) ev.extraInfo; uuid_unparse(connEv->uid,cuid_str); uuid_unparse(process_uid,puid_str); msgLen = snprintf(eventMessageSQL, MAX_EVENT_SQL_LEN, "INSERT INTO servers (uid,repeater_uid,lasttime,status,table_index,code,mode,ip) VALUES ('%s','%s',%ld,%d,%d,%ld,%d,'%d.%d.%d.%d');\n", cuid_str,puid_str,ev.timeStamp, status,connEv->tableIndex,connEv->code,connEv->connMode, connEv->peerIp.a,connEv->peerIp.b,connEv->peerIp.c,connEv->peerIp.d); break; case SERVER_DISCONNECT: status = 0; connEv = (connectionEvent *) ev.extraInfo; uuid_unparse(connEv->uid,cuid_str); msgLen = snprintf(eventMessageSQL, MAX_EVENT_SQL_LEN, "UPDATE servers SET lasttime = %ld,status = %d WHERE uid = '%s';\n", ev.timeStamp, status,cuid_str); break; case VIEWER_SERVER_SESSION_START: status = 1; sessEv = (sessionEvent *) ev.extraInfo; uuid_unparse(sessEv->server_uid,cuid_str); uuid_unparse(sessEv->viewer_uid,cuid_str2); uuid_unparse(process_uid,puid_str); msgLen = snprintf(eventMessageSQL, MAX_EVENT_SQL_LEN, "INSERT INTO sessions (repeater_uid,status,lasttime,server_index,server_ip,server_uid,viewer_index,viewer_ip,viewer_uid,code,mode) " "VALUES ('%s',%d,%ld,%d,'%d.%d.%d.%d','%s',%d,'%d.%d.%d.%d','%s',%ld,%d);\n", puid_str,status,ev.timeStamp, sessEv -> serverTableIndex,sessEv->serverIp.a, sessEv->serverIp.b, sessEv->serverIp.c, sessEv->serverIp.d,cuid_str, sessEv -> viewerTableIndex,sessEv->viewerIp.a, sessEv->viewerIp.b, sessEv->viewerIp.c, sessEv->viewerIp.d,cuid_str2, sessEv -> code, sessEv -> connMode); break; case VIEWER_SERVER_SESSION_END: status = 0; sessEv = (sessionEvent *) ev.extraInfo; uuid_unparse(process_uid,puid_str); uuid_unparse(sessEv->server_uid,cuid_str); uuid_unparse(sessEv->viewer_uid,cuid_str2); msgLen = snprintf(eventMessageSQL, MAX_EVENT_SQL_LEN, "UPDATE sessions SET status=%d,lasttime=%ld WHERE repeater_uid='%s' AND server_uid='%s' AND viewer_uid='%s';\n", status,ev.timeStamp,puid_str,cuid_str,cuid_str2); break; case REPEATER_STARTUP: status = 1; seEv = (startEndEvent *) ev.extraInfo; uuid_unparse(process_uid,puid_str); msgLen = snprintf(eventMessageSQL, MAX_EVENT_SQL_LEN, "INSERT INTO repeaters (uid,process_id,lasttime,status,maxsessions,ip,server_port,viewer_port) VALUES ('%s',%d,%ld,%d,%d,'%s',%d,%d);\n", puid_str,ev.repeaterProcessId,ev.timeStamp, status, seEv -> maxSessions, ownIpAddress,serverPort,viewerPort); break; case REPEATER_SHUTDOWN: status = 0; seEv = (startEndEvent *) ev.extraInfo; uuid_unparse(process_uid,puid_str); msgLen = snprintf(eventMessageSQL, MAX_EVENT_SQL_LEN, "UPDATE repeaters SET lasttime=%ld,status=%d WHERE uid='%s';\n", ev.timeStamp, status, puid_str); break; case REPEATER_HEARTBEAT: uuid_unparse(process_uid,puid_str); msgLen = snprintf(eventMessageSQL, MAX_EVENT_SQL_LEN, "UPDATE repeaters SET lasttime=%ld WHERE uid='%s';\n", ev.timeStamp, puid_str); break; default: msgLen = 0; strlcpy(eventMessageSQL, "\n", MAX_EVENT_SQL_LEN); break; } if (msgLen > 0) { mysql_query(&mysql,eventMessageSQL); if(mysql_errno(&mysql)) { debug(LEVEL_1,"MYSQL ERROR: %s\n",mysql_error(&mysql)); } debug(LEVEL_1, "%s", eventMessageSQL); } } mysql_close(&mysql); } } #endif //EVENTS_USE_MYSQL return 0; }