void CommModuleProcessReceivedMessage(C1222AL* p, ACSE_Message* pMsg) { // this routine processes a message received from the meter Boolean isSegmented; Unsigned16 sequence; // the message might be directed at this comm module, or might be intended to be transmitted to the network //if ( CommModule_IsMessageForMe(p, pMsg) ) // CommModuleRequestServer_handleMessage(p, pMsg); //else //{ (void)pMsg; // if this is a segmented message, we will disable registration for a traffic timeout to avoid // problems with a registration request replacing an in progress segmented message down the line // like in a relay that is reassembling messages if ( ACSE_Message_IsSegmented(pMsg, &isSegmented) && isSegmented ) { p->status.lastCMSegmentedMessagePromotion = C1222Misc_GetFreeRunningTimeInMS(); } else p->status.lastCMSegmentedMessagePromotion = 0; // check if this was a registration response when we are already registered // if so, ignore it if ( p->counters.registrationAttempts > 0 ) { if ( (C1222Misc_GetFreeRunningTimeInMS()-p->status.lastRegistrationAttemptTime) < 60000L ) { if ( ACSE_Message_GetCalledApInvocationId( pMsg, &sequence) ) { if ( sequence == p->status.registrationRequestApInvocationId ) { // we got here because we are no longer waiting for the registration response, // probably because we already handled the reg response // so if we get another one, ignore it // anyway, the reg response should not be passed to the register C1222AL_LogEvent(p, C1222EVENT_AL_DISCARDEDEXTRAREGRESPONSE); return; } } } } // let the comm module handle the message C1222AL_NoteReceivedCompleteMessage(p); //*********** //} }
static void CommModuleWaitForRegistrationResponse(C1222AL* p) { Unsigned32 now; // need to check once in awhile if it has been too long and send the request again now = C1222Misc_GetFreeRunningTimeInMS(); if ( (now-p->status.lastRegistrationAttemptTime) > (p->status.registrationRetrySeconds*1000L) ) // wait 20 secs //2 minutes for now { p->status.timeToRegister = TRUE; p->status.state = ALS_IDLE; p->status.registrationInProgress = FALSE; C1222AL_SetRegistrationRetryTime(p); } else if ( !p->status.sendingRegistrationRequest ) { // let the transport layer run to keep the device happy // will need to handle messages from the device now in this state! // until the registration request has been sent out the other stack // ignore our lower layers to avoid adding a new message to the mix C1222TL_Run( (C1222TL*)(p->pTransport) ); } }
static void CommModuleHandleTimeToRegister(C1222AL* p) { C1222TransportConfig* pConfig = &p->transportConfig; if ( (C1222Misc_GetFreeRunningTimeInMS()-p->status.lastCMSegmentedMessagePromotion) < 20000 ) { return; // wait a bit to prevent overwriting a downstream partially assembled message // with the registration request } if ( p->status.timeToRegister && p->status.haveConfiguration && (!C1222AL_IsBusy(p)) && p->status.isReceivedMessageHandlingComplete && !p->status.isReceivedMessageComplete ) { if ( (C1222Misc_GetUIDLength(pConfig->esn) <= 2) && (C1222Misc_GetUIDLength(pConfig->nodeApTitle) <= 2) ) { p->status.registrationFailureReason = MFC_REG_ESN_INVALID; C1222AL_LogEvent(p, C1222EVENT_AL_ESN_INVALID); // should log something return; } if ( (C1222Misc_GetUIDLength(pConfig->esn) > C1222_ESN_LENGTH) || (C1222Misc_GetUIDLength(pConfig->nodeApTitle) > C1222_APTITLE_LENGTH) ) { p->status.registrationFailureReason = MFC_REG_ESN_OR_APTITLE_TOO_LONG; C1222AL_LogEvent(p, C1222EVENT_AL_ESN_OR_APTITLE_TOOLONG); // should log something return; } CommModuleSendRegistrationRequestToNetwork(p); p->status.state = ALS_REGISTERING; p->status.registrationInProgress = TRUE; p->status.registrationFailureReason = MFG_REG_DEREG_PENDING_OR_TIMEOUT; // pending or timeout p->status.lastRegistrationAttemptTime = C1222Misc_GetFreeRunningTimeInMS(); p->status.timeToRegister = FALSE; } }
static void CommModuleSendingMessage(C1222AL* p) { C1222TL* pTransport = (C1222TL*)(p->pTransport); if ( (C1222Misc_GetFreeRunningTimeInMS()-p->status.sendStartTime) > (p->status.sendTimeOutSeconds*1000L) ) { p->counters.sendTimedOut++; C1222AL_LogEvent(p, C1222EVENT_AL_SENDTIMEDOUT); C1222AL_TL_NoteFailedSendMessage(p); } else C1222TL_Run( pTransport ); }
Boolean CommModuleHandleNetworkMessageDuringRegistration(C1222AL* p, ACSE_Message* pMsg, Unsigned8 addressLength, Unsigned8* nativeAddress) { Unsigned16 apInvocationId; // until we are registered, we probably don't want to accept any messages // for one thing we probably don't have an aptitle // need to determine if this message is a registration response // can do that by comparing the called ap invocation id to the saved registration ap invocation id if ( ACSE_Message_GetCalledApInvocationId(pMsg, &apInvocationId) ) { if ( apInvocationId == p->status.registrationRequestApInvocationId ) { if ( CommModuleHandleRegistrationResponse(p, pMsg, addressLength, nativeAddress) ) // Checks if it is a valid response and saves all the info from the response { p->status.lastSuccessfulRegistrationTime = C1222Misc_GetFreeRunningTimeInMS(); p->counters.registrationSuccessCount++; C1222AL_SetRegisteredStatus(p, TRUE); p->status.registrationInProgress = FALSE; p->status.state = ALS_IDLE; C1222AL_LogEvent(p, C1222EVENT_AL_REGISTERED); } else C1222AL_LogEvent(p, C1222EVENT_AL_REG_RESPONSE_INVALID); return TRUE; // it was a registration response and we handled it - either saved the info or considered it as a failure, so it does not // need to be sent down the stack } C1222AL_LogEvent(p, C1222EVENT_AL_OTHER_MESSAGE_WAITING_FOR_REG_RESPONSE); // if not a registration response, I'm going to ignore it } // if no apInvocation id, cannot be a registration response - or I can't tell, so ignore it return FALSE; // the message was not consumed here - send it on to the stack }
Unsigned8 C1222MessageReceiver_AddSegment(C1222MessageReceiver* p, Unsigned8 nativeAddressLength, Unsigned8* nativeAddress, ACSE_Message* pMsg) { Unsigned16 offset; Unsigned16 fullLength; Unsigned16 sequence; Boolean isSegmented; C1222AL* pApplication = (C1222AL*)(p->pApplication); // need to check for request too large if ( pMsg->length > MAX_ACSE_MESSAGE_LENGTH ) { C1222MessageReceiver_LogEvent(p, C1222EVENT_ALR_ADDSEG_MSG_TOO_LONG); return C1222RESPONSE_RQTL; } if ( ACSE_Message_GetSegmentOffset(pMsg, &offset, &fullLength, &sequence) ) { // this is a segmented message if ( fullLength > MAX_ACSE_MESSAGE_LENGTH ) { C1222MessageReceiver_LogEvent(p, C1222EVENT_ALR_ADDSEG_FULLMSG_TOO_LONG); return C1222RESPONSE_RQTL; } } // save the native address if ( nativeAddressLength > C1222_NATIVE_ADDRESS_LENGTH ) nativeAddressLength = C1222_NATIVE_ADDRESS_LENGTH; p->nativeAddressLength = nativeAddressLength; memset(p->nativeAddress, 0, C1222_NATIVE_ADDRESS_LENGTH); memcpy(p->nativeAddress, nativeAddress, nativeAddressLength); // get segmentation info if ( !ACSE_Message_IsSegmented(pMsg, &isSegmented) ) { C1222MessageReceiver_LogEvent(p, C1222EVENT_ALR_ADDSEG_GET_SEG_STATUS_ERR); return C1222RESPONSE_SGERR; } if ( isSegmented ) { if ( C1222ALSegmenter_IsSegmentAlreadyReceived(&p->receiveSegmenter, pMsg) ) { pApplication->counters.duplicateSegmentIgnored++; C1222MessageReceiver_LogEvent(p, C1222EVENT_ALR_DUPLICATE_SEGMENT); // will return ok - message will not be complete if it was not complete before } else if ( !C1222ALSegmenter_SetSegment(&p->receiveSegmenter, pMsg) ) { C1222MessageReceiver_LogEvent(p, C1222EVENT_ALR_CANT_SET_SEGMENT); return C1222RESPONSE_SGERR; } } else { // if we are in the process of receiving a segmented message, and this is a display update from the rflan // fail the message to avoid trashing the segmented message if ( C1222ALSegmenter_IsBusy(&p->receiveSegmenter) ) { #if 0 // this is no longer needed since there are no low priority messages from the rflan if ( IsLowPriorityMessageFromRFLAN(p, pMsg) ) { ((C1222AL*)(p->pApplication))->counters.rflanMessageIgnored++; C1222MessageReceiver_LogEvent(p, C1222EVENT_ALR_IGNOREDRFLANMESSAGE); return C1222RESPONSE_BSY; } #endif ((C1222AL*)(p->pApplication))->counters.partialMessageOverLayedByLaterFullMessage++; ((C1222AL*)(p->pApplication))->status.timeOfLastDiscardedSegmentedMessage = C1222Misc_GetFreeRunningTimeInMS(); } // the message is copied to the receive segmenter just to have someplace to store it // it currently resides in the transport layer buffer which is apparently big enough // so this should not fail if ( !C1222ALSegmenter_SetUnsegmentedRxMessage(&p->receiveSegmenter, pMsg) ) { C1222MessageReceiver_LogEvent(p, C1222EVENT_ALR_CANT_SET_UNSEG_MSG2); return C1222RESPONSE_SGERR; } C1222ALSegmenter_EndNewUnsegmentedMessage(&p->receiveSegmenter); } return C1222RESPONSE_OK; }
void C1222Server_ProcessMessage(C1222Server* p, ACSE_Message* pMsg, Boolean* pMessageWasSent, Boolean bDoNotNoteReceivedMessageHandlingIsComplete) { ACSE_Message responseMessage; Unsigned8* nativeAddress; Unsigned8 addressLength; C1222AL* pAppLayer = (C1222AL*)(&p->pStack->Xapplication); C1222MessageFailureCode reason; C1222MessageLogEntry logEntry; *pMessageWasSent = FALSE; ACSE_Message_SetBuffer(&responseMessage, p->meterResponseBuffer, MAX_ACSE_MESSAGE_LENGTH); ACSE_Message_SetStandardVersion( &responseMessage, ACSE_Message_GetStandardVersion(pMsg) ); C1222AL_MakeMessageLogEntry(pAppLayer, pMsg, &logEntry, FALSE, C1222_MSGTYPE_REQUEST); // this is a receiving log entry C1222AL_LogComEventAndBytes(pAppLayer, COMEVENT_RECEIVED_MESSAGE_FROM, &logEntry, sizeof(logEntry)); if ( C1222Server_ProcessMeterMessage(p, pMsg, &responseMessage) ) { pAppLayer->lastMessageLog.responseReadyToSend = C1222Misc_GetFreeRunningTimeInMS(); if ( !bDoNotNoteReceivedMessageHandlingIsComplete && !p->sendToNonC1222Stack ) C1222Stack_NoteReceivedMessageHandlingIsComplete(p->pStack); if ( C1222Stack_GetReceivedMessageNativeAddress(p->pStack, &addressLength, &nativeAddress) ) { #ifdef C1222_COMM_MODULE if ( 0 == memcmp(nativeAddress, p->pStack->Xapplication.transportConfig.broadcastAddress, addressLength) ) { nativeAddress = p->pStack->Xapplication.transportConfig.nativeAddress; addressLength = p->pStack->Xapplication.transportConfig.nativeAddressLength; } if ( p->sendToNonC1222Stack ) *pMessageWasSent = C1222Stack_SendMessageToNonC1222Stack(&responseMessage, nativeAddress, addressLength); else #endif *pMessageWasSent = C1222Stack_SendMessage(p->pStack, &responseMessage, nativeAddress, addressLength); C1222AL_MakeMessageLogEntry(pAppLayer, &responseMessage, &logEntry, TRUE, C1222_MSGTYPE_RESPONSE); // this is a receiving log entry C1222AL_LogComEventAndBytes(pAppLayer, COMEVENT_SENT_MESSAGE_TO, &logEntry, sizeof(logEntry)); C1222AL_LogComEvent(pAppLayer, COMEVENT_C1222_SENT_RESPONSE); if ( *pMessageWasSent ) C1222AL_LogComEvent(pAppLayer, COMEVENT_C1222_SEND_RESPONSE_SUCCESS); else { reason = MFC_SEND_MESSAGE_FAILED; C1222AL_LogComEventAndBytes(pAppLayer, COMEVENT_C1222_SEND_RESPONSE_FAILED, &reason, sizeof(reason)); } } } else if ( !p->sendToNonC1222Stack ) { if ( p->processMessageResponse != C1222RESPONSE_OK ) C1222Server_SimpleResponse(p, pMsg, p->processMessageResponse); else C1222Stack_NoteReceivedMessageHandlingIsComplete(p->pStack); } // log message handling here to take care of the cases when there is no response C1222AL_LogComEventAndBytes(pAppLayer, COMEVENT_C1222_PROCESS_RCVD_MSG_TIMING, &pAppLayer->lastMessageLog, sizeof(pAppLayer->lastMessageLog)); }
static void CommModuleHandleAutoRegistration(C1222AL* p) { C1222TL* pTransport = (C1222TL*)(p->pTransport); Unsigned32 now = C1222Misc_GetFreeRunningTimeInMS(); Unsigned16 minutes; C1222TransportConfig* pConfig = &p->transportConfig; if ( !C1222TL_IsReady(pTransport) ) return; if ( C1222AL_IsBusy(p) ) return; if ( !p->status.isSynchronizedOrConnected ) { p->status.registrationFailureReason = MFC_REG_NOT_SYNCHRONIZED; p->status.timeToRegister = FALSE; return; } if ( !p->status.isRegistered ) { // in order to register, need an esn or an aptitle if ( (C1222Misc_GetUIDLength(pConfig->esn) <= 2) && (C1222Misc_GetUIDLength(pConfig->nodeApTitle) <= 2) ) { // an event here would be too busy since this will be called lots return; } // if not registered and auto registration is on, better register // we might want to implement a random delay here // TODO: !! if ( (now-(p->status.lastRegistrationAttemptTime)) > (p->status.registrationRetrySeconds*1000L) ) { C1222AL_LogEvent(p, C1222EVENT_AL_TIME_TO_REGISTER); p->status.timeToRegister = TRUE; } } else if ( p->registrationStatus.regPeriodMinutes != 0 ) { // currently registered - handle keep alive if ( p->registrationStatus.regCountDownMinutes == 0 ) { if ( p->status.state != ALS_REGISTERING ) { C1222AL_LogEvent(p, C1222EVENT_AL_TIME_TO_REFRESH_REGISTRATION); p->status.timeToRegister = TRUE; } } else { now = C1222Misc_GetFreeRunningTimeInMS(); minutes = (Unsigned16)((now - p->status.lastSuccessfulRegistrationTime)/60000L); if ( minutes < p->registrationStatus.regPeriodMinutes ) p->registrationStatus.regCountDownMinutes = (Unsigned16)(p->registrationStatus.regPeriodMinutes - minutes); else p->registrationStatus.regCountDownMinutes = 0; } } // else don't need to refresh registration }
extern "C" void TcpIpServerThread(void* dummy) { char* ipaddress; int bytesSent; int bytesRecv; SOCKET m_socket; SOCKET save_m_socket; sockaddr_in service; hostent* localHost; SOCKET AcceptSocket; int iResult,displayed_message = 0; int ii; unsigned char waitingForResponseFromStack = FALSE; unsigned char socketReady = FALSE; unsigned long waitingForResponseFromStackStart = 0; (void)dummy; iResult = WSAStartup( MAKEWORD(2,2), &wsaData ); if ( iResult != NO_ERROR ) printf("Error in WSAStartup() = %d\n", WSAGetLastError()); // Create a socket. m_socket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); if ( m_socket == INVALID_SOCKET ) { printf( "Error in socket(): %ld\n", WSAGetLastError() ); WSACleanup(); return; } // Bind the socket. service.sin_family = AF_INET; // Get the local host information localHost = gethostbyname(""); ipaddress = inet_ntoa (*(struct in_addr *)*localHost->h_addr_list); printf("Using ip address = '%s'\n", ipaddress); //service.sin_addr.s_addr = inet_addr( ipaddress ); service.sin_addr.s_addr = htonl( INADDR_ANY ); service.sin_port = htons( (unsigned short)g_server_port ); if ( bind( m_socket, (SOCKADDR*) &service, sizeof(service) ) == SOCKET_ERROR ) { printf( "bind() failed error=%d.\n", WSAGetLastError() ); closesocket(m_socket); return; } // Listen on the socket. if ( listen( m_socket, 1 ) == SOCKET_ERROR ) printf( "Error listening on socket. Error=%d\n", WSAGetLastError()); // Accept connections. //printf( "Waiting for a client to connect...\n" ); save_m_socket = m_socket; while(1) { if ( !socketReady ) { if(displayed_message == 0){ printf( "TCP : Waiting for a client to connect...\n" ); displayed_message = 1; } AcceptSocket = accept(m_socket, NULL, NULL ); if ( AcceptSocket != SOCKET_ERROR ) { m_socket = AcceptSocket; socketReady = TRUE; } displayed_message = 0; } if ( g_sendReady && socketReady ) { memcpy(sendbuf, g_sendBuffer, g_sendLength); bytesSent = send( m_socket, sendbuf, g_sendLength, 0); if ( bytesSent == SOCKET_ERROR || bytesSent < 0 ) { printf("socket error in send = %d\n", WSAGetLastError()); m_socket = save_m_socket; socketReady = FALSE; } else { strcpy(traceBuffer,"Tx->\n"); for ( ii=0; ii<g_sendLength; ii++ ) { sprintf(myBuffer, " %02X", g_sendBuffer[ii] & 0xFF); strcat(traceBuffer, myBuffer); if ( ii%20 == 19 ) { printf("%s\n", traceBuffer); strcpy(traceBuffer,""); } } printf("%s\n",traceBuffer); if ( separateReply ) { m_socket = save_m_socket; socketReady = FALSE; } } waitingForResponseFromStack = FALSE; g_sendReady = FALSE; } if ( socketReady && !waitingForResponseFromStack ) { // lets see if there is a message for me bytesRecv = recv( m_socket, (char*)recvbuf, 1000, MSG_PEEK ); if ( bytesRecv != SOCKET_ERROR ) { if ( bytesRecv > 0 ) bytesRecv = recv( m_socket, (char*)recvbuf, bytesRecv, 0); if ( bytesRecv > 0 ) { strcpy(traceBuffer,"Rx<-\n"); for ( ii=0; ii<bytesRecv; ii++ ) { sprintf(myBuffer, " %02X", recvbuf[ii]&0xFF); strcat(traceBuffer, myBuffer); if ( ii%20 == 19 ) { printf("%s\n", traceBuffer); strcpy(traceBuffer,""); } } printf("%s\n", traceBuffer); waitingForResponseFromStack = doCMProcessReceivedStreamBytes(recvbuf, bytesRecv); if ( waitingForResponseFromStack ) waitingForResponseFromStackStart = C1222Misc_GetFreeRunningTimeInMS(); if ( waitingForResponseFromStack && separateReply ) waitingForResponseFromStack = FALSE; } receivedChunks++; totalReceivedBytes += bytesRecv; if ( bytesRecv == 0 ) { printf("socket closed\n"); m_socket = save_m_socket; socketReady = FALSE; } else if ( bytesRecv < 0 ) { printf("socket error in recv1 = %d\n", WSAGetLastError()); m_socket = save_m_socket; socketReady = FALSE; } } else { printf("socket error in recv = %d\n", WSAGetLastError()); m_socket = save_m_socket; socketReady = FALSE; } } if ( waitingForResponseFromStack ) { if ( (C1222Misc_GetFreeRunningTimeInMS()-waitingForResponseFromStackStart) > 60000L ) waitingForResponseFromStack = FALSE; } DoSleep(100); } }
void C1222Stack_CancelPartiallyReceivedMessage(C1222Stack* p) { C1222MessageReceiver_CancelPartialMessage(&p->Xapplication.messageReceiver); p->Xapplication.counters.partialMessageCanceled++; p->Xapplication.status.timeOfLastDiscardedSegmentedMessage = C1222Misc_GetFreeRunningTimeInMS(); }