Files
rpc/MicroLMS/heci/LMEConnection.c

555 lines
18 KiB
C

/* INTEL CONFIDENTIAL
* Copyright 2011 - 2019 Intel Corporation.
* This software and the related documents are Intel copyrighted materials, and your use of them is governed by the express license under which they were provided to you ("License"). Unless the License provides otherwise, you may not use, modify, copy, publish, distribute, disclose or transmit this software or the related documents without Intel's prior written permission.
* This software and the related documents are provided as is, with no express or implied warranties, other than those that are expressly stated in the License.
*/
#ifndef _MINCORE
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "LMEConnection.h"
#include "LMS_if.h"
#include "../microstack/ILibParsers.h"
#ifdef _POSIX
#define UNREFERENCED_PARAMETER(P) (P)
#endif
#define MEI_IO_TIMEOUT 1000
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
const unsigned int LME_RX_WINDOW_SIZE = 4096;
int LME_sendMessage(struct LMEConnection* module, unsigned char *buffer, int len);
void LME_doRX(struct LMEConnection* module, unsigned char *rxBuffer, unsigned int bytesRead);
void LME_apfGlobalRequest(struct LMEConnection* module, unsigned char *rxBuffer, unsigned int bytesRead, int *status);
void LME_Deinit(struct LMEConnection* module);
bool LME_IsInitialized(struct LMEConnection* module)
{
// Lock il(_initLock);
bool ret = (bool)(module->initState == INIT_STATE_CONNECTED);
return ret;
}
#ifdef WIN32
DWORD WINAPI LME_Thread(void* obj)
#else
void LME_Thread(void* obj)
#endif
{
#ifdef WIN32
HECI_VERSION version;
#endif
int len = 0;
int bufsize = 0;
unsigned char* data = NULL;
struct LMEConnection* module = (struct LMEConnection*)obj;
//printf("LMS THREAD START\r\n");
do {
bufsize = heci_GetBufferSize(&(module->mei));
if ((data = (unsigned char*)malloc(bufsize)) == NULL) ILIBCRITICALEXIT(254);
do {
len = heci_ReceiveMessage(&(module->mei), data, bufsize, 0xFFFFFFFF);
//printf("LMS THREAD READ LEN=%d\r\n", len);
if (len > 0 && data != NULL) LME_doRX(module, data, len);
} while (len >= 0);
module->cb(module, module->cbParam, NULL, 0);
module->initState = INIT_STATE_DISCONNECTED;
free(data);
// printf("LMS TRYING RECONNECT\r\n");
while (module->exit == 0 && module->initState == INIT_STATE_DISCONNECTED)
{
// Setup the MEI interface with the LME GUID
#ifdef WIN32
if (heci_Init(&(module->mei), LMS_CLIENT) == TRUE && heci_GetHeciVersion(&(module->mei), &version) == TRUE && version.major >= LMS_PROTOCOL_VERSION) { module->initState = INIT_STATE_CONNECTED; }
#else
if (heci_Init(&(module->mei), 1) == TRUE && heci_GetProtocolVersion(&(module->mei)) >= LMS_PROTOCOL_VERSION) { module->initState = INIT_STATE_CONNECTED; }
#endif
if (module->exit == 0 && module->initState == INIT_STATE_DISCONNECTED)
{
// printf("LMS THREAD SLEEP\r\n");
#ifdef WIN32
Sleep(2000);
#else
sleep(2);
#endif
}
//if (module->initState == INIT_STATE_CONNECTED) printf("LMS THREAD RECONNECT\r\n");
}
}
while (module->exit == 0);
// printf("LMS THREAD QUIT\r\n");
module->exit = 2;
#ifdef WIN32
return 0;
#endif
}
// Setup the LME connection
bool LME_Init(struct LMEConnection* module, MEICallback cb, void *param)
{
#ifdef WIN32
HECI_VERSION version;
#endif
// Setup the state object
memset(module, 0, sizeof(struct LMEConnection));
module->initState = INIT_STATE_DISCONNECTED;
module->cb = cb;
module->cbParam = param;
// Setup the MEI interface with the LME GUID
#ifdef WIN32
if (heci_Init(&(module->mei), LMS_CLIENT) == FALSE || heci_GetHeciVersion(&(module->mei), &version) == FALSE || version.major < LMS_PROTOCOL_VERSION) { module->initState = INIT_STATE_DISCONNECTED; return FALSE; }
#else
if (heci_Init(&(module->mei), 1) == FALSE || heci_GetProtocolVersion(&(module->mei)) < LMS_PROTOCOL_VERSION) { module->initState = INIT_STATE_DISCONNECTED; return FALSE; }
#endif
module->initState = INIT_STATE_CONNECTED;
if ((module->txBuffer = (unsigned char*)malloc(LME_GetMeiBufferSize(module))) == NULL) ILIBCRITICALEXIT(254);
// Create the thread that will read the MEI/LME stream
ILibSpawnNormalThread((voidfp)(&LME_Thread), module);
return TRUE;
}
// Disconnect the LME connection
void LME_Deinit(struct LMEConnection* module)
{
//printf("LME_Deinit()\r\n");
if (module == NULL) return;
if (module->initState == INIT_STATE_CONNECTED) { heci_Deinit(&(module->mei)); }
module->initState = INIT_STATE_DISCONNECTED;
}
// Exit LME
void LME_Exit(struct LMEConnection* module)
{
int l = 0;
//printf("LME_Exit()\r\n");
if (module == NULL) return;
if (module->exit == 0) module->exit = 1;
LME_Deinit(module);
#ifdef WIN32
while (module->exit != 2 && l < 40) { Sleep(100); l++; }
#else
/*
while (module->exit != 2 && l < 4)
{
printf("LME_Holding %d\r\n", l);
Sleep(1);
l++;
}
*/
#endif
if (module->txBuffer != NULL && l < 40) { free(module->txBuffer); module->txBuffer = NULL; }
}
// Send the APF disconnect message to the MEI
bool LME_Disconnect(struct LMEConnection* module, APF_DISCONNECT_REASON_CODE reasonCode)
{
unsigned char buf[sizeof(APF_DISCONNECT_MESSAGE)];
APF_DISCONNECT_MESSAGE *disconnectMessage = (APF_DISCONNECT_MESSAGE *)buf;
memset(disconnectMessage, 0, sizeof(buf));
disconnectMessage->MessageType = APF_DISCONNECT;
disconnectMessage->ReasonCode = htonl(reasonCode);
return (LME_sendMessage(module, buf, sizeof(buf)) == sizeof(buf));
}
// Send the AFP service accept message to the MEI
bool LME_ServiceAccept(struct LMEConnection* module, char* serviceName)
{
int len;
int res;
int servicenamelen = (int)strnlen_s(serviceName, _MAX_PATH);
unsigned char *buf;
unsigned char *pCurrent;
if (!LME_IsInitialized(module)) return FALSE;
if ((buf = (unsigned char*)malloc(sizeof(APF_SERVICE_ACCEPT_MESSAGE) + servicenamelen)) == NULL) ILIBCRITICALEXIT(254);
pCurrent = buf;
*pCurrent = APF_SERVICE_ACCEPT;
++pCurrent;
*((unsigned int *)pCurrent) = htonl(servicenamelen);
pCurrent += 4;
memcpy_s(pCurrent, sizeof(APF_SERVICE_ACCEPT_MESSAGE) + servicenamelen, serviceName, servicenamelen);
pCurrent += servicenamelen;
len = (int)(pCurrent - buf);
res = LME_sendMessage(module, buf, len);
free(buf);
return (res == len);
}
bool LME_ProtocolVersion(struct LMEConnection* module, unsigned int majorversion, unsigned int minorversion, unsigned int triggerreason)
{
APF_PROTOCOL_VERSION_MESSAGE protVersion;
memset(&protVersion, 0, sizeof(protVersion));
protVersion.MessageType = APF_PROTOCOLVERSION;
protVersion.MajorVersion = htonl(majorversion);
protVersion.MinorVersion = htonl(minorversion);
protVersion.TriggerReason = htonl(triggerreason);
return (LME_sendMessage(module, (unsigned char *)&protVersion, sizeof(protVersion)) == sizeof(protVersion));
}
bool LME_TcpForwardReplySuccess(struct LMEConnection* module, unsigned int port)
{
APF_TCP_FORWARD_REPLY_MESSAGE message;
memset(&message, 0, sizeof(message));
message.MessageType = APF_REQUEST_SUCCESS;
message.PortBound = htonl(port);
return (LME_sendMessage(module, (unsigned char *)&message, sizeof(message)) == sizeof(message));
}
bool LME_SendShortMessage(struct LMEConnection* module, unsigned char buf)
{
return (LME_sendMessage(module, &buf, sizeof(buf)) == sizeof(buf));
}
#define pCurrentOffset ((int)(pCurrent - buf))
bool LME_ChannelOpenForwardedRequest(struct LMEConnection* module, unsigned int senderChannel, char* connectedIP, unsigned int connectedPort, char* originatorIP, unsigned int originatorPort)
{
int res;
int connectedIPlen = (int)strnlen_s(connectedIP, _MAX_PATH);
int originatorIPlen = (int)strnlen_s(originatorIP, _MAX_PATH);
unsigned char *buf;
unsigned char *pCurrent;
int mallocSize = 5 + APF_STR_SIZE_OF(APF_OPEN_CHANNEL_REQUEST_FORWARDED) + 16 + connectedIPlen + 8 + originatorIPlen + 4;
if (!LME_IsInitialized(module)) return FALSE;
if ((buf = (unsigned char*)malloc(mallocSize)) == NULL) ILIBCRITICALEXIT(254);
pCurrent = buf;
if (strnlen_s(originatorIP, _MAX_PATH) > 63) { free(buf); return FALSE; }
*pCurrent = APF_CHANNEL_OPEN;
++pCurrent;
*((unsigned int *)pCurrent) = htonl(APF_STR_SIZE_OF(APF_OPEN_CHANNEL_REQUEST_FORWARDED));
pCurrent += sizeof(unsigned int);
memcpy_s(pCurrent, mallocSize - pCurrentOffset, APF_OPEN_CHANNEL_REQUEST_FORWARDED, APF_STR_SIZE_OF(APF_OPEN_CHANNEL_REQUEST_FORWARDED));
pCurrent += APF_STR_SIZE_OF(APF_OPEN_CHANNEL_REQUEST_FORWARDED);
*((unsigned int *)pCurrent) = htonl(senderChannel);
pCurrent += sizeof(unsigned int);
*((unsigned int *)pCurrent) = htonl(LME_RX_WINDOW_SIZE);
pCurrent += sizeof(unsigned int);
*((unsigned int *)pCurrent) = 0xFFFFFFFF;
pCurrent += sizeof(unsigned int);
*((unsigned int *)pCurrent) = htonl(connectedIPlen);
pCurrent += sizeof(unsigned int);
memcpy_s(pCurrent, mallocSize - pCurrentOffset, connectedIP, connectedIPlen);
pCurrent += connectedIPlen;
*((unsigned int *)pCurrent) = htonl(connectedPort);
pCurrent += sizeof(unsigned int);
*((unsigned int *)pCurrent) = htonl((unsigned int)originatorIPlen);
pCurrent += sizeof(unsigned int);
memcpy_s(pCurrent, mallocSize - pCurrentOffset, originatorIP, originatorIPlen);
pCurrent += originatorIPlen;
*((unsigned int *)pCurrent) = htonl(originatorPort);
pCurrent += sizeof(unsigned int);
res = LME_sendMessage(module, buf, (int)(pCurrent - buf));
free(buf);
return (res == pCurrent - buf);
}
bool LME_ChannelOpenReplySuccess(struct LMEConnection* module, unsigned int recipientChannel, unsigned int senderChannel)
{
APF_CHANNEL_OPEN_CONFIRMATION_MESSAGE message;
message.MessageType = APF_CHANNEL_OPEN_CONFIRMATION;
message.RecipientChannel = htonl(recipientChannel);
message.SenderChannel = htonl(senderChannel);
message.InitialWindowSize = htonl(LME_RX_WINDOW_SIZE);
message.Reserved = 0xFFFFFFFF;
return (LME_sendMessage(module, (unsigned char*)&message, sizeof(message)) == sizeof(message));
}
bool LME_ChannelOpenReplyFailure(struct LMEConnection* module, unsigned int recipientChannel, unsigned int reason)
{
APF_CHANNEL_OPEN_FAILURE_MESSAGE message;
message.MessageType = APF_CHANNEL_OPEN_FAILURE;
message.RecipientChannel = htonl(recipientChannel);
message.ReasonCode = htonl(reason);
message.Reserved = 0x00000000;
message.Reserved2 = 0x00000000;
return (LME_sendMessage(module, (unsigned char*)&message, sizeof(message)) == sizeof(message));
}
bool LME_ChannelClose(struct LMEConnection* module, unsigned int recipientChannel, unsigned int senderChannel )
{
APF_CHANNEL_CLOSE_MESSAGE message;
UNREFERENCED_PARAMETER( senderChannel );
message.MessageType = APF_CHANNEL_CLOSE;
message.RecipientChannel = htonl(recipientChannel);
return (LME_sendMessage(module, (unsigned char*)&message, sizeof(message)) == sizeof(message));
}
int LME_ChannelData(struct LMEConnection* module, unsigned int recipientChannel, unsigned int len, unsigned char *buffer)
{
APF_CHANNEL_DATA_MESSAGE *message;
if (len > (LME_GetMeiBufferSize(module) - sizeof(APF_CHANNEL_DATA_MESSAGE)) || module->txBuffer == NULL) return -1;
message = (APF_CHANNEL_DATA_MESSAGE*)module->txBuffer;
message->MessageType = APF_CHANNEL_DATA;
message->RecipientChannel = htonl(recipientChannel);
message->DataLength = htonl(len);
memcpy_s(module->txBuffer + sizeof(APF_CHANNEL_DATA_MESSAGE), LME_GetMeiBufferSize(module) - sizeof(APF_CHANNEL_DATA_MESSAGE), buffer, len);
return LME_sendMessage(module, (unsigned char *)message, sizeof(APF_CHANNEL_DATA_MESSAGE) + len) - sizeof(APF_CHANNEL_DATA_MESSAGE);
}
bool LME_ChannelWindowAdjust(struct LMEConnection* module, unsigned int recipientChannel, unsigned int len)
{
APF_WINDOW_ADJUST_MESSAGE message;
message.MessageType = APF_CHANNEL_WINDOW_ADJUST;
message.RecipientChannel = htonl(recipientChannel);
message.BytesToAdd = htonl(len);
return (LME_sendMessage(module, (unsigned char *)&message, sizeof(message)) == sizeof(message));
}
int LME_sendMessage(struct LMEConnection* module, unsigned char *buffer, int len)
{
int result;
if (!LME_IsInitialized(module)) { return -1; }
result = heci_SendMessage(&(module->mei), buffer, len, MEI_IO_TIMEOUT);
if (result < 0) LME_Deinit(module);
return result;
}
bool LME_checkMinMsgSize(unsigned char *buf, unsigned int bytesRead)
{
switch (buf[0]) {
case APF_DISCONNECT:
if (bytesRead < sizeof(APF_DISCONNECT_MESSAGE)) { return FALSE; }
break;
case APF_SERVICE_REQUEST:
if (bytesRead < sizeof(APF_SERVICE_REQUEST_MESSAGE)) { return FALSE; }
if (bytesRead < (sizeof(APF_SERVICE_REQUEST_MESSAGE) + ntohl(((APF_SERVICE_REQUEST_MESSAGE *)buf)->ServiceNameLength))) { return FALSE; }
break;
case APF_USERAUTH_REQUEST:
if (bytesRead < (3 * sizeof(unsigned int))) { return FALSE; }
break;
case APF_GLOBAL_REQUEST:
if (bytesRead < (sizeof(APF_GENERIC_HEADER) + sizeof(UINT8))) { return FALSE; }
if (bytesRead < (sizeof(APF_GENERIC_HEADER) + sizeof(UINT8) + ntohl(((APF_GENERIC_HEADER *)buf)->StringLength))) { return FALSE; }
break;
case APF_CHANNEL_OPEN:
if (bytesRead < sizeof(APF_GENERIC_HEADER)) { return FALSE; }
if (bytesRead < (sizeof(APF_GENERIC_HEADER) + ntohl(((APF_GENERIC_HEADER *)buf)->StringLength))) { return FALSE; }
break;
case APF_CHANNEL_OPEN_CONFIRMATION:
if (bytesRead < sizeof(APF_CHANNEL_OPEN_CONFIRMATION_MESSAGE)) { return FALSE; }
break;
case APF_CHANNEL_OPEN_FAILURE:
if (bytesRead < sizeof(APF_CHANNEL_OPEN_FAILURE_MESSAGE)) { return FALSE; }
break;
case APF_CHANNEL_CLOSE:
if (bytesRead < sizeof(APF_CHANNEL_CLOSE_MESSAGE)) { return FALSE; }
break;
case APF_CHANNEL_DATA:
if (bytesRead < sizeof(APF_CHANNEL_DATA_MESSAGE)) { return FALSE; }
if (bytesRead < (sizeof(APF_CHANNEL_DATA_MESSAGE) + ntohl(((APF_CHANNEL_DATA_MESSAGE *)buf)->DataLength))) { return FALSE; }
break;
case APF_CHANNEL_WINDOW_ADJUST:
if (bytesRead < sizeof(APF_WINDOW_ADJUST_MESSAGE)) { return FALSE; }
break;
case APF_PROTOCOLVERSION:
if (bytesRead < sizeof(APF_PROTOCOL_VERSION_MESSAGE)) { return FALSE; }
break;
default:
return FALSE;
}
return TRUE;
}
void LME_doRX(struct LMEConnection* module, unsigned char *rxBuffer, unsigned int bytesRead)
{
if (bytesRead == 0) return;
if (!LME_checkMinMsgSize(rxBuffer, bytesRead)) { LME_Deinit(module); return; }
module->cb(module, module->cbParam, rxBuffer, bytesRead);
}
/*
void LME_apfChannelOpen(struct LMEConnection* module, unsigned char *rxBuffer, unsigned int bytesRead, int *status)
{
APF_GENERIC_HEADER *pHeader = (APF_GENERIC_HEADER *)rxBuffer;
if (_strnicmp((char *)pHeader->String, APF_OPEN_CHANNEL_REQUEST_DIRECT, APF_STR_SIZE_OF(APF_OPEN_CHANNEL_REQUEST_DIRECT)) == 0)
{
unsigned int senderChannel = 0;
LME_apfChannelOpenDirect(module, rxBuffer, bytesRead, &senderChannel, status);
if (LME_IsInitialized(module) && (*status == 1)) {
if (plugin.retry(rxBuffer, bytesRead) != LMS_DROPPED) { LME_apfChannelOpenDirect(module, rxBuffer, bytesRead, NULL, status); }
}
if (LME_IsInitialized(module) && (*status == 1)) {
LME_ChannelOpenReplyFailure(module, senderChannel, OPEN_FAILURE_REASON_CONNECT_FAILED);
}
}
}
void LME_apfChannelOpenDirect(struct LMEConnection* module, unsigned char *rxBuffer, unsigned int bytesRead, unsigned int *senderChannel, int *status)
{
unsigned char *pCurrent;
APF_GENERIC_HEADER *pHeader = (APF_GENERIC_HEADER *)rxBuffer;
if (bytesRead < sizeof(APF_GENERIC_HEADER) +
ntohl(pHeader->StringLength) +
7 + (5 * sizeof(unsigned int))) {
ILIBMESSAGE("apfChannelOpenDirect: Error receiving data from MEI\n");
LME_Deinit(module);
return;
}
pCurrent = rxBuffer + sizeof(APF_GENERIC_HEADER) +
APF_STR_SIZE_OF(APF_OPEN_CHANNEL_REQUEST_DIRECT);
LMEChannelOpenRequestMessage channelOpenRequest;
channelOpenRequest.ChannelType = APF_CHANNEL_DIRECT;
channelOpenRequest.SenderChannel = ntohl(*((unsigned int *)pCurrent));
if (senderChannel) {
*senderChannel = channelOpenRequest.SenderChannel;
}
pCurrent += sizeof(unsigned int);
channelOpenRequest.InitialWindow = ntohl(*((unsigned int *)pCurrent));
pCurrent += 2 * sizeof(unsigned int);
unsigned int len = ntohl(*((unsigned int *)pCurrent));
pCurrent += sizeof(unsigned int);
channelOpenRequest.Address.append((char *)pCurrent, len);
pCurrent += len;
channelOpenRequest.Port = ntohl(*((unsigned int *)pCurrent));
pCurrent += sizeof(unsigned int);
module->_cb(module, module->_cbParam, &channelOpenRequest, sizeof(channelOpenRequest), status);
}
*/
/*
void LME_apfUserAuthRequest(struct LMEConnection* module, unsigned char *rxBuffer, unsigned int bytesRead, int *status)
{
unsigned char *pCurrent = rxBuffer;
++pCurrent;
LMEUserAuthRequestMessage userAuthRequest;
unsigned int len = ntohl(*((unsigned int *)pCurrent));
pCurrent += sizeof(unsigned int);
if ((bytesRead - (pCurrent - rxBuffer)) < len) {
ILIBMESSAGE("_apfUserAuthRequest1: Error receiving data from MEI\n");
LME_Deinit(module);
return;
}
userAuthRequest.Username.append((char *)pCurrent, len);
pCurrent += len;
if ((unsigned int)(bytesRead - (pCurrent - rxBuffer)) < sizeof(unsigned int)) {
ILIBMESSAGE("_apfUserAuthRequest2: Error receiving data from MEI\n");
LME_Deinit(module);
return;
}
len = ntohl(*((unsigned int *)pCurrent));
pCurrent += sizeof(unsigned int);
if ((bytesRead - (pCurrent - rxBuffer)) < len) {
ILIBMESSAGE("_apfUserAuthRequest3: Error receiving data from MEI\n");
LME_Deinit(module);
return;
}
userAuthRequest.ServiceName.append((char *)pCurrent, len);
pCurrent += len;
if ((unsigned int)(bytesRead - (pCurrent - rxBuffer)) < sizeof(unsigned int)) {
ILIBMESSAGE("_apfUserAuthRequest4: Error receiving data from MEI\n");
LME_Deinit(module);
return;
}
len = ntohl(*((unsigned int *)pCurrent));
pCurrent += sizeof(unsigned int);
if ((bytesRead - (pCurrent - rxBuffer)) < len) {
ILIBMESSAGE("_apfUserAuthRequest5: Error receiving data from MEI\n");
LME_Deinit(module);
return;
}
userAuthRequest.MethodName.append((char *)pCurrent, len);
pCurrent += len;
if (_strnicmp(userAuthRequest.MethodName.c_str(), APF_AUTH_PASSWORD,
userAuthRequest.MethodName.size()) == 0) {
if ((unsigned int)(bytesRead - (pCurrent - rxBuffer)) < sizeof(unsigned int) + 1) {
ILIBMESSAGE("_apfUserAuthRequest6: Error receiving data from MEI\n");
LME_Deinit(module);
return;
}
++pCurrent;
len = ntohl(*((unsigned int *)pCurrent));
pCurrent += sizeof(unsigned int);
if ((bytesRead - (pCurrent - rxBuffer)) < len) {
ILIBMESSAGE("_apfUserAuthRequest7: Error receiving data from MEI\n");
LME_Deinit(module);
return;
}
AuthPasswordData authData;
authData.Password.append((char *)pCurrent, len);
pCurrent += len;
userAuthRequest.MethodData = &authData;
}
module->_cb(module, module->_cbParam, &userAuthRequest, sizeof(userAuthRequest), status);
}
*/
unsigned int LME_GetMeiBufferSize(struct LMEConnection* module)
{
return heci_GetBufferSize(&(module->mei));
}
#endif