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);
    }
}
Beispiel #10
0
void C1222Stack_CancelPartiallyReceivedMessage(C1222Stack* p)
{
    C1222MessageReceiver_CancelPartialMessage(&p->Xapplication.messageReceiver);
    p->Xapplication.counters.partialMessageCanceled++;
    p->Xapplication.status.timeOfLastDiscardedSegmentedMessage = C1222Misc_GetFreeRunningTimeInMS();
}