Developer Experience Release. Added LMS and code refactor.
This commit is contained in:
614
MicroLMS/microstack/ILibAsyncServerSocket.c
Normal file
614
MicroLMS/microstack/ILibAsyncServerSocket.c
Normal file
@@ -0,0 +1,614 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#if defined(WIN32) && !defined(_MINCORE)
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include <stdlib.h>
|
||||
#include <crtdbg.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#define SOCKET_ERROR (-1)
|
||||
#define UNREFERENCED_PARAMETER(P) (P)
|
||||
#endif
|
||||
|
||||
#if defined(WINSOCK2)
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#elif defined(WINSOCK1)
|
||||
#include <winsock.h>
|
||||
#include <wininet.h>
|
||||
#endif
|
||||
|
||||
#include "ILibParsers.h"
|
||||
#include "ILibAsyncServerSocket.h"
|
||||
#include "ILibAsyncSocket.h"
|
||||
|
||||
#define DEBUGSTATEMENT(x)
|
||||
|
||||
#define INET_SOCKADDR_LENGTH(x) ((x==AF_INET6?sizeof(struct sockaddr_in6):sizeof(struct sockaddr_in)))
|
||||
|
||||
typedef struct ILibAsyncServerSocketModule
|
||||
{
|
||||
ILibChain_Link ChainLink;
|
||||
|
||||
int MaxConnection;
|
||||
void **AsyncSockets;
|
||||
ILibServerScope scope;
|
||||
|
||||
SOCKET ListenSocket;
|
||||
unsigned short portNumber, initialPortNumber;
|
||||
int listening;
|
||||
int loopbackFlag;
|
||||
|
||||
ILibAsyncServerSocket_OnReceive OnReceive;
|
||||
ILibAsyncServerSocket_OnConnect OnConnect;
|
||||
ILibAsyncServerSocket_OnDisconnect OnDisconnect;
|
||||
ILibAsyncServerSocket_OnInterrupt OnInterrupt;
|
||||
ILibAsyncServerSocket_OnSendOK OnSendOK;
|
||||
|
||||
void *Tag;
|
||||
int Tag2;
|
||||
|
||||
}ILibAsyncServerSocketModule;
|
||||
struct ILibAsyncServerSocket_Data
|
||||
{
|
||||
struct ILibAsyncServerSocketModule *module;
|
||||
ILibAsyncServerSocket_BufferReAllocated Callback;
|
||||
void *user;
|
||||
};
|
||||
|
||||
const int ILibMemory_ASYNCSERVERSOCKET_CONTAINERSIZE = (const int)sizeof(ILibAsyncServerSocketModule);
|
||||
|
||||
|
||||
/*! \fn ILibAsyncServerSocket_GetTag(ILibAsyncServerSocket_ServerModule ILibAsyncSocketModule)
|
||||
\brief Returns the user Tag associated with the AsyncServer
|
||||
\param ILibAsyncSocketModule The ILibAsyncServerSocket to query
|
||||
\returns The user Tag
|
||||
*/
|
||||
void *ILibAsyncServerSocket_GetTag(ILibAsyncServerSocket_ServerModule ILibAsyncSocketModule)
|
||||
{
|
||||
return (((struct ILibAsyncServerSocketModule*)ILibAsyncSocketModule)->Tag);
|
||||
}
|
||||
/*! \fn ILibAsyncServerSocket_SetTag(ILibAsyncServerSocket_ServerModule ILibAsyncSocketModule, void *tag)
|
||||
\brief Sets the user Tag associated with the AsyncServer
|
||||
\param ILibAsyncSocketModule The ILibAsyncServerSocket to save the tag to
|
||||
\param tag The value to save
|
||||
*/
|
||||
void ILibAsyncServerSocket_SetTag(ILibAsyncServerSocket_ServerModule ILibAsyncSocketModule, void *tag)
|
||||
{
|
||||
((struct ILibAsyncServerSocketModule*)ILibAsyncSocketModule)->Tag = tag;
|
||||
}
|
||||
|
||||
/*! \fn ILibAsyncServerSocket_GetTag(ILibAsyncServerSocket_ServerModule ILibAsyncSocketModule)
|
||||
\brief Returns the user Tag associated with the AsyncServer
|
||||
\param ILibAsyncSocketModule The ILibAsyncServerSocket to query
|
||||
\returns The user Tag
|
||||
*/
|
||||
int ILibAsyncServerSocket_GetTag2(ILibAsyncServerSocket_ServerModule ILibAsyncSocketModule)
|
||||
{
|
||||
return(((struct ILibAsyncServerSocketModule*)ILibAsyncSocketModule)->Tag2);
|
||||
}
|
||||
/*! \fn ILibAsyncServerSocket_SetTag(ILibAsyncServerSocket_ServerModule ILibAsyncSocketModule, void *tag)
|
||||
\brief Sets the user Tag associated with the AsyncServer
|
||||
\param ILibAsyncSocketModule The ILibAsyncServerSocket to save the tag to
|
||||
\param tag The value to save
|
||||
*/
|
||||
void ILibAsyncServerSocket_SetTag2(ILibAsyncServerSocket_ServerModule ILibAsyncSocketModule, int tag)
|
||||
{
|
||||
((struct ILibAsyncServerSocketModule*)ILibAsyncSocketModule)->Tag2 = tag;
|
||||
}
|
||||
|
||||
//
|
||||
// Internal method called by ILibAsyncSocket, to signal an interrupt condition
|
||||
//
|
||||
// <param name="socketModule">The ILibAsyncServerSocket that was interrupted</param>
|
||||
// <param name="user">The associated user tag</param>
|
||||
void ILibAsyncServerSocket_OnInterruptSink(ILibAsyncSocket_SocketModule socketModule, void *user)
|
||||
{
|
||||
struct ILibAsyncServerSocket_Data *data = (struct ILibAsyncServerSocket_Data*)user;
|
||||
if (data == NULL) return;
|
||||
if (data->module->OnInterrupt != NULL) data->module->OnInterrupt(data->module, socketModule, data->user);
|
||||
free(user);
|
||||
}
|
||||
//
|
||||
// Chain PreSelect handler
|
||||
//
|
||||
// <param name="socketModule"></param>
|
||||
// <param name="readset"></param>
|
||||
// <param name="writeset"></param>
|
||||
// <param name="errorset"></param>
|
||||
// <param name="blocktime"></param>
|
||||
void ILibAsyncServerSocket_PreSelect(void* socketModule, fd_set *readset, fd_set *writeset, fd_set *errorset, int* blocktime)
|
||||
{
|
||||
struct ILibAsyncServerSocketModule *module = (struct ILibAsyncServerSocketModule*)socketModule;
|
||||
int flags,i;
|
||||
|
||||
UNREFERENCED_PARAMETER( writeset );
|
||||
UNREFERENCED_PARAMETER( errorset );
|
||||
UNREFERENCED_PARAMETER( blocktime );
|
||||
|
||||
//
|
||||
// The socket isn't put in listening mode, until the chain is started.
|
||||
// If this variable == 0, that means we need to do that.
|
||||
//
|
||||
if (module->listening == 0)
|
||||
{
|
||||
//
|
||||
// Set the socket to non-block mode, so we can play nice and share the thread
|
||||
//
|
||||
#ifdef WIN32
|
||||
flags = 1;
|
||||
if(ioctlsocket(module->ListenSocket, FIONBIO, (u_long *)(&flags)) == SOCKET_ERROR) ILIBCRITICALEXIT2(246, WSAGetLastError());
|
||||
#elif _POSIX
|
||||
flags = fcntl(module->ListenSocket, F_GETFL,0);
|
||||
fcntl(module->ListenSocket, F_SETFL, O_NONBLOCK | flags);
|
||||
#endif
|
||||
|
||||
//
|
||||
// Put the socket in Listen, and add it to the fdset for the Select loop
|
||||
//
|
||||
module->listening = 1;
|
||||
listen(module->ListenSocket, 4);
|
||||
#if defined(WIN32)
|
||||
#pragma warning( push, 3 ) // warning C4127: conditional expression is constant
|
||||
#endif
|
||||
FD_SET(module->ListenSocket, readset);
|
||||
#if defined(WIN32)
|
||||
#pragma warning( pop )
|
||||
#endif
|
||||
}
|
||||
else if (module->ListenSocket != ~0)
|
||||
{
|
||||
// Only put the ListenSocket in the readset, if we are able to handle a new socket
|
||||
for(i = 0; i < module->MaxConnection; ++i)
|
||||
{
|
||||
if (ILibAsyncSocket_IsFree(module->AsyncSockets[i]) != 0)
|
||||
{
|
||||
#if defined(WIN32)
|
||||
#pragma warning( push, 3 ) // warning C4127: conditional expression is constant
|
||||
#endif
|
||||
FD_SET(module->ListenSocket, readset);
|
||||
#if defined(WIN32)
|
||||
#pragma warning( pop )
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*! \fn ILibAsyncServerSocket_SetReAllocateNotificationCallback(ILibAsyncServerSocket_ServerModule AsyncServerSocketToken, ILibAsyncServerSocket_ConnectionToken ConnectionToken, ILibAsyncServerSocket_BufferReAllocated Callback)
|
||||
\brief Set the callback handler for when the internal data buffer has been resized
|
||||
\param AsyncServerSocketToken The ILibAsyncServerSocket to query
|
||||
\param ConnectionToken The specific connection to set the callback with
|
||||
\param Callback The callback handler to set
|
||||
*/
|
||||
void ILibAsyncServerSocket_SetReAllocateNotificationCallback(ILibAsyncServerSocket_ServerModule AsyncServerSocketToken, ILibAsyncServerSocket_ConnectionToken ConnectionToken, ILibAsyncServerSocket_BufferReAllocated Callback)
|
||||
{
|
||||
struct ILibAsyncServerSocket_Data *data = (struct ILibAsyncServerSocket_Data*)ILibAsyncSocket_GetUser(ConnectionToken);
|
||||
UNREFERENCED_PARAMETER( AsyncServerSocketToken );
|
||||
if (data != NULL) data->Callback = Callback;
|
||||
}
|
||||
|
||||
//
|
||||
// Chain PostSelect handler
|
||||
//
|
||||
// <param name="socketModule"></param>
|
||||
// <param name="slct"></param>
|
||||
// <param name="readset"></param>
|
||||
// <param name="writeset"></param>
|
||||
// <param name="errorset"></param>
|
||||
void ILibAsyncServerSocket_PostSelect(void* socketModule, int slct, fd_set *readset, fd_set *writeset, fd_set *errorset)
|
||||
{
|
||||
struct ILibAsyncServerSocket_Data *data;
|
||||
struct sockaddr_in6 addr;
|
||||
#ifdef _POSIX
|
||||
socklen_t addrlen;
|
||||
#else
|
||||
int addrlen;
|
||||
#endif
|
||||
|
||||
struct ILibAsyncServerSocketModule *module = (struct ILibAsyncServerSocketModule*)socketModule;
|
||||
int i,flags;
|
||||
#ifdef WIN32
|
||||
SOCKET NewSocket;
|
||||
#elif defined( _POSIX)
|
||||
int NewSocket;
|
||||
#endif
|
||||
|
||||
UNREFERENCED_PARAMETER( slct );
|
||||
UNREFERENCED_PARAMETER( writeset );
|
||||
UNREFERENCED_PARAMETER( errorset );
|
||||
|
||||
if (FD_ISSET(module->ListenSocket, readset) != 0)
|
||||
{
|
||||
//
|
||||
// There are pending TCP connection requests
|
||||
//
|
||||
for(i = 0; i < module->MaxConnection; ++i)
|
||||
{
|
||||
//
|
||||
// Check to see if we have available resources to handle this connection request
|
||||
//
|
||||
if (ILibAsyncSocket_IsFree(module->AsyncSockets[i]) != 0)
|
||||
{
|
||||
addrlen = sizeof(addr);
|
||||
NewSocket = accept(module->ListenSocket, (struct sockaddr*)&addr, &addrlen); // Klocwork claims we could lose the resource acquired fom the declaration, but that is not possible in this case
|
||||
|
||||
if (NewSocket != ~0)
|
||||
{
|
||||
//printf("Accepting new connection, socket = %d\r\n", NewSocket);
|
||||
//
|
||||
// Set this new socket to non-blocking mode, so we can play nice and share thread
|
||||
//
|
||||
#ifdef WIN32
|
||||
flags = 1;
|
||||
if (ioctlsocket(NewSocket, FIONBIO, (u_long *)(&flags)) == SOCKET_ERROR) ILIBCRITICALEXIT2(246, WSAGetLastError());
|
||||
#elif _POSIX
|
||||
flags = fcntl(NewSocket, F_GETFL,0);
|
||||
fcntl(NewSocket, F_SETFL, O_NONBLOCK|flags);
|
||||
#endif
|
||||
//
|
||||
// Instantiate a module to contain all the data about this connection
|
||||
//
|
||||
if ((data = (struct ILibAsyncServerSocket_Data*)malloc(sizeof(struct ILibAsyncServerSocket_Data))) == NULL) ILIBCRITICALEXIT(254);
|
||||
memset(data, 0, sizeof(struct ILibAsyncServerSocket_Data));
|
||||
data->module = (struct ILibAsyncServerSocketModule*)socketModule;
|
||||
|
||||
ILibAsyncSocket_UseThisSocket(module->AsyncSockets[i], NewSocket, &ILibAsyncServerSocket_OnInterruptSink, data);
|
||||
ILibAsyncSocket_SetRemoteAddress(module->AsyncSockets[i], (struct sockaddr*)&addr);
|
||||
|
||||
if (module->OnConnect != NULL)
|
||||
{
|
||||
// Notify the user about this new connection
|
||||
module->OnConnect(module, module->AsyncSockets[i], &(data->user));
|
||||
}
|
||||
}
|
||||
else {break;}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // Klocwork claims that we could lose the resource acquired in the declaration, but that is not possible in this case
|
||||
//
|
||||
// Chain Destroy handler
|
||||
//
|
||||
// <param name="socketModule"></param>
|
||||
void ILibAsyncServerSocket_Destroy(void *socketModule)
|
||||
{
|
||||
struct ILibAsyncServerSocketModule *module =(struct ILibAsyncServerSocketModule*)socketModule;
|
||||
|
||||
free(module->AsyncSockets);
|
||||
if (module->ListenSocket != (SOCKET)~0)
|
||||
{
|
||||
#ifdef WIN32
|
||||
closesocket(module->ListenSocket);
|
||||
#elif _POSIX
|
||||
close(module->ListenSocket);
|
||||
#endif
|
||||
module->ListenSocket = (SOCKET)~0;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Internal method dispatched by the OnData event of the underlying ILibAsyncSocket
|
||||
//
|
||||
// <param name="socketModule"></param>
|
||||
// <param name="buffer"></param>
|
||||
// <param name="p_beginPointer"></param>
|
||||
// <param name="endPointer"></param>
|
||||
// <param name="OnInterrupt"></param>
|
||||
// <param name="user"></param>
|
||||
// <param name="PAUSE"></param>
|
||||
void ILibAsyncServerSocket_OnData(ILibAsyncSocket_SocketModule socketModule,char* buffer,int *p_beginPointer, int endPointer,void (**OnInterrupt)(void *AsyncSocketMoudle, void *user),void **user, int *PAUSE)
|
||||
{
|
||||
struct ILibAsyncServerSocket_Data *data = (struct ILibAsyncServerSocket_Data*)(*user);
|
||||
int bpointer = *p_beginPointer;
|
||||
|
||||
UNREFERENCED_PARAMETER( OnInterrupt );
|
||||
|
||||
// Pass the received data up
|
||||
if (data != NULL && data->module->OnReceive != NULL)
|
||||
{
|
||||
data->module->OnReceive(data->module, socketModule, buffer, &bpointer, endPointer, &(data->module->OnInterrupt), &(data->user), PAUSE);
|
||||
if (ILibAsyncSocket_IsFree(socketModule))
|
||||
{
|
||||
*p_beginPointer = endPointer;
|
||||
}
|
||||
else
|
||||
{
|
||||
*p_beginPointer = bpointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
// Internal method dispatched by the OnConnect event of the underlying ILibAsyncSocket. In this case, it will only occur when TLS connection is established.
|
||||
//
|
||||
// <param name="socketModule"></param>
|
||||
// <param name="user"></param>
|
||||
void ILibAsyncServerSocket_OnConnectSink(ILibAsyncSocket_SocketModule socketModule, int Connected, void *user)
|
||||
{
|
||||
struct ILibAsyncServerSocket_Data *data = (struct ILibAsyncServerSocket_Data*)user;
|
||||
|
||||
if (data == NULL) return;
|
||||
if (Connected == 0)
|
||||
{
|
||||
// Connection Failed, clean up
|
||||
free(data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (data->module->OnConnect != NULL) data->module->OnConnect(data->module, socketModule, &(data->user));
|
||||
}
|
||||
//
|
||||
// Internal method dispatched by the OnDisconnect event of the underlying ILibAsyncSocket
|
||||
//
|
||||
// <param name="socketModule"></param>
|
||||
// <param name="user"></param>
|
||||
void ILibAsyncServerSocket_OnDisconnectSink(ILibAsyncSocket_SocketModule socketModule, void *user)
|
||||
{
|
||||
struct ILibAsyncServerSocket_Data *data = (struct ILibAsyncServerSocket_Data*)user;
|
||||
|
||||
// Pass this Disconnect event up
|
||||
if (data == NULL) return;
|
||||
if (data->module->OnDisconnect != NULL) data->module->OnDisconnect(data->module, socketModule, data->user);
|
||||
|
||||
// If the chain is shutting down, we need to free some resources
|
||||
if (ILibIsChainBeingDestroyed(data->module->ChainLink.ParentChain) == 0) free(data);
|
||||
}
|
||||
//
|
||||
// Internal method dispatched by the OnSendOK event of the underlying ILibAsyncSocket
|
||||
//
|
||||
// <param name="socketModule"></param>
|
||||
// <param name="user"></param>
|
||||
void ILibAsyncServerSocket_OnSendOKSink(ILibAsyncSocket_SocketModule socketModule, void *user)
|
||||
{
|
||||
struct ILibAsyncServerSocket_Data *data = (struct ILibAsyncServerSocket_Data*)user;
|
||||
|
||||
// Pass the OnSendOK event up
|
||||
if (data != NULL && data->module->OnSendOK != NULL) data->module->OnSendOK(data->module, socketModule, data->user);
|
||||
}
|
||||
//
|
||||
// Internal method dispatched by ILibAsyncSocket, to signal that the buffers have been reallocated
|
||||
//
|
||||
// <param name="ConnectionToken">The ILibAsyncSocket sender</param>
|
||||
// <param name="user">The ILibAsyncServerSocket_Data object</param>
|
||||
// <param name="offSet">The offset to the new buffer location</param>
|
||||
void ILibAsyncServerSocket_OnBufferReAllocated(ILibAsyncSocket_SocketModule ConnectionToken, void *user, ptrdiff_t offSet)
|
||||
{
|
||||
struct ILibAsyncServerSocket_Data *data = (struct ILibAsyncServerSocket_Data*)user;
|
||||
if (data!=NULL && data->Callback!=NULL)
|
||||
{
|
||||
//
|
||||
// If someone above us, has registered for this callback, we need to fire it,
|
||||
// with the correct user object
|
||||
//
|
||||
data->Callback(data->module,ConnectionToken,data->user,offSet);
|
||||
}
|
||||
}
|
||||
|
||||
void ILibAsyncServerSocket_ResumeListeningSink(void *chain, void* user)
|
||||
{
|
||||
ILibAsyncServerSocketModule *m = (ILibAsyncServerSocketModule*)user;
|
||||
|
||||
int ra = 1;
|
||||
int off = 0;
|
||||
int receivingAddressLength = sizeof(struct sockaddr_in6);
|
||||
struct sockaddr_in6 localif;
|
||||
struct sockaddr_in6 localAddress;
|
||||
|
||||
UNREFERENCED_PARAMETER(chain);
|
||||
|
||||
memset(&localif, 0, sizeof(struct sockaddr_in6));
|
||||
if (m->loopbackFlag != 2 && ILibDetectIPv6Support())
|
||||
{
|
||||
// Setup the IPv6 any or loopback address, this socket will also work for IPv4 traffic on IPv6 stack
|
||||
localif.sin6_family = AF_INET6;
|
||||
localif.sin6_addr = (m->loopbackFlag != 0 ? in6addr_loopback : in6addr_any);
|
||||
localif.sin6_port = htons(m->initialPortNumber);
|
||||
}
|
||||
else
|
||||
{
|
||||
// IPv4-only detected
|
||||
localif.sin6_family = AF_INET;
|
||||
#ifdef WINSOCK2
|
||||
((struct sockaddr_in*)&localif)->sin_addr.S_un.S_addr = htonl((m->loopbackFlag != 0 ? INADDR_LOOPBACK : INADDR_ANY));
|
||||
#else
|
||||
((struct sockaddr_in*)&localif)->sin_addr.s_addr = htonl((m->loopbackFlag != 0 ? INADDR_LOOPBACK : INADDR_ANY));
|
||||
#endif
|
||||
((struct sockaddr_in*)&localif)->sin_port = htons(m->initialPortNumber);
|
||||
}
|
||||
|
||||
// Get our listening socket
|
||||
if ((m->ListenSocket = socket(localif.sin6_family, SOCK_STREAM, IPPROTO_TCP)) == -1) { m->ListenSocket = (SOCKET)~0; return; }
|
||||
|
||||
// Setup the IPv6 & IPv4 support on same socket
|
||||
if (localif.sin6_family == AF_INET6) if (setsockopt(m->ListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&off, sizeof(off)) != 0) ILIBCRITICALERREXIT(253);
|
||||
|
||||
#ifdef SO_NOSIGPIPE
|
||||
setsockopt(m->ListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&ra, sizeof(int)); // Turn off SIGPIPE if writing to disconnected socket
|
||||
#endif
|
||||
|
||||
#if defined(WIN32)
|
||||
// On Windows. Lets make sure no one else can bind to this addr/port. This stops socket hijacking (not a problem on Linux).
|
||||
if (setsockopt(m->ListenSocket, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char*)&ra, sizeof(int)) != 0) ILIBCRITICALERREXIT(253);
|
||||
#else
|
||||
// On Linux. Setting the re-use on a TCP socket allows reuse of the socket even in timeout state. Allows for fast stop/start (Not a problem on Windows).
|
||||
if (setsockopt(m->ListenSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&ra, sizeof(int)) != 0) ILIBCRITICALERREXIT(253);
|
||||
#endif
|
||||
|
||||
// Bind the socket
|
||||
#if defined(WIN32)
|
||||
if (bind(m->ListenSocket, (struct sockaddr*)&localif, INET_SOCKADDR_LENGTH(localif.sin6_family)) != 0) { closesocket(m->ListenSocket); m->ListenSocket = (SOCKET)~0; return; }
|
||||
#else
|
||||
if (bind(m->ListenSocket, (struct sockaddr*)&localif, INET_SOCKADDR_LENGTH(localif.sin6_family)) != 0) { close(m->ListenSocket); m->ListenSocket = (SOCKET)~0; return; }
|
||||
#endif
|
||||
|
||||
// Fetch the local port number
|
||||
#if defined(WINSOCK2)
|
||||
getsockname(m->ListenSocket, (struct sockaddr*)&localAddress, (int*)&receivingAddressLength);
|
||||
#else
|
||||
getsockname(m->ListenSocket, (struct sockaddr*)&localAddress, (socklen_t*)&receivingAddressLength);
|
||||
#endif
|
||||
if (localAddress.sin6_family == AF_INET6) m->portNumber = ntohs(localAddress.sin6_port); else m->portNumber = ntohs(((struct sockaddr_in*)&localAddress)->sin_port);
|
||||
m->listening = 0;
|
||||
}
|
||||
void ILibAsyncServerSocket_StopListeningSink(void *chain, void* user)
|
||||
{
|
||||
ILibAsyncServerSocketModule *m = (ILibAsyncServerSocketModule*)user;
|
||||
UNREFERENCED_PARAMETER(chain);
|
||||
|
||||
if (m->ListenSocket != (SOCKET)~0)
|
||||
{
|
||||
#ifdef WIN32
|
||||
closesocket(m->ListenSocket);
|
||||
#else
|
||||
close(m->ListenSocket);
|
||||
#endif
|
||||
m->ListenSocket = (SOCKET)~0;
|
||||
}
|
||||
}
|
||||
//! Take the server socket out of listening mode, rejecting new incoming connection requests
|
||||
/*!
|
||||
\param module ILibAsyncServerSocket_ServerModule Server Listening Module
|
||||
*/
|
||||
void ILibAsyncServerSocket_StopListening(ILibAsyncServerSocket_ServerModule module)
|
||||
{
|
||||
ILibAsyncServerSocketModule *m = (ILibAsyncServerSocketModule*)module;
|
||||
ILibChain_RunOnMicrostackThread(m->ChainLink.ParentChain, ILibAsyncServerSocket_StopListeningSink, m);
|
||||
}
|
||||
//! Put the server socket back in listening mode, to allow new incoming connection requests
|
||||
/*!
|
||||
\param module ILibAsyncServerSocket_ServerModule Server Listening Module
|
||||
*/
|
||||
void ILibAsyncServerSocket_ResumeListening(ILibAsyncServerSocket_ServerModule module)
|
||||
{
|
||||
ILibAsyncServerSocketModule *m = (ILibAsyncServerSocketModule*)module;
|
||||
ILibChain_RunOnMicrostackThread(m->ChainLink.ParentChain, ILibAsyncServerSocket_ResumeListeningSink, m);
|
||||
}
|
||||
|
||||
|
||||
/*! \fn ILibCreateAsyncServerSocketModule(void *Chain, int MaxConnections, int PortNumber, int initialBufferSize, ILibAsyncServerSocket_OnConnect OnConnect,ILibAsyncServerSocket_OnDisconnect OnDisconnect,ILibAsyncServerSocket_OnReceive OnReceive,ILibAsyncServerSocket_OnInterrupt OnInterrupt, ILibAsyncServerSocket_OnSendOK OnSendOK)
|
||||
\brief Instantiates a new ILibAsyncServerSocket
|
||||
\param Chain The chain to add this module to. (Chain must <B>not</B> be running)
|
||||
\param MaxConnections The max number of simultaneous connections that will be allowed
|
||||
\param PortNumber The port number to bind to. 0 will select a random port
|
||||
\param initialBufferSize The initial size of the receive buffer
|
||||
\param loopbackFlag 0 to bind to ANY, 1 to bind to IPv6 loopback first, 2 to bind to IPv4 loopback first.
|
||||
\param OnConnect Function Pointer that triggers when a connection is established
|
||||
\param OnDisconnect Function Pointer that triggers when a connection is closed
|
||||
\param OnReceive Function Pointer that triggers when data is received
|
||||
\param OnInterrupt Function Pointer that triggers when connection interrupted
|
||||
\param OnSendOK Function Pointer that triggers when pending sends are complete
|
||||
\param ServerAutoFreeMemorySize Size of AutoFreeMemory on Server to co-allocate
|
||||
\param SessionAutoFreeMemorySize Size of AutoFreeMemory on Session to co-allocate
|
||||
\returns An ILibAsyncServerSocket module
|
||||
*/
|
||||
ILibAsyncServerSocket_ServerModule ILibCreateAsyncServerSocketModuleWithMemory(void *Chain, int MaxConnections, unsigned short PortNumber, int initialBufferSize, int loopbackFlag, ILibAsyncServerSocket_OnConnect OnConnect, ILibAsyncServerSocket_OnDisconnect OnDisconnect, ILibAsyncServerSocket_OnReceive OnReceive, ILibAsyncServerSocket_OnInterrupt OnInterrupt, ILibAsyncServerSocket_OnSendOK OnSendOK, int ServerUserMappedMemorySize, int SessionUserMappedMemorySize)
|
||||
{
|
||||
int i;
|
||||
int ra = 1;
|
||||
int off = 0;
|
||||
int receivingAddressLength = sizeof(struct sockaddr_in6);
|
||||
struct sockaddr_in6 localif;
|
||||
struct sockaddr_in6 localAddress;
|
||||
struct ILibAsyncServerSocketModule *RetVal;
|
||||
|
||||
memset(&localif, 0, sizeof(struct sockaddr_in6));
|
||||
if (loopbackFlag != 2 && ILibDetectIPv6Support())
|
||||
{
|
||||
// Setup the IPv6 any or loopback address, this socket will also work for IPv4 traffic on IPv6 stack
|
||||
localif.sin6_family = AF_INET6;
|
||||
localif.sin6_addr = (loopbackFlag != 0?in6addr_loopback:in6addr_any);
|
||||
localif.sin6_port = htons(PortNumber);
|
||||
}
|
||||
else
|
||||
{
|
||||
// IPv4-only detected
|
||||
localif.sin6_family = AF_INET;
|
||||
#ifdef WINSOCK2
|
||||
((struct sockaddr_in*)&localif)->sin_addr.S_un.S_addr = htonl((loopbackFlag != 0?INADDR_LOOPBACK:INADDR_ANY));
|
||||
#else
|
||||
((struct sockaddr_in*)&localif)->sin_addr.s_addr = htonl((loopbackFlag != 0?INADDR_LOOPBACK:INADDR_ANY));
|
||||
#endif
|
||||
((struct sockaddr_in*)&localif)->sin_port = htons(PortNumber);
|
||||
}
|
||||
|
||||
// Instantiate a new AsyncServer module
|
||||
RetVal = (struct ILibAsyncServerSocketModule*)ILibChain_Link_Allocate(sizeof(struct ILibAsyncServerSocketModule), ServerUserMappedMemorySize);
|
||||
|
||||
RetVal->ChainLink.PreSelectHandler = &ILibAsyncServerSocket_PreSelect;
|
||||
RetVal->ChainLink.PostSelectHandler = &ILibAsyncServerSocket_PostSelect;
|
||||
RetVal->ChainLink.DestroyHandler = &ILibAsyncServerSocket_Destroy;
|
||||
RetVal->ChainLink.ParentChain = Chain;
|
||||
RetVal->OnConnect = OnConnect;
|
||||
RetVal->OnDisconnect = OnDisconnect;
|
||||
RetVal->OnInterrupt = OnInterrupt;
|
||||
RetVal->OnSendOK = OnSendOK;
|
||||
RetVal->OnReceive = OnReceive;
|
||||
RetVal->MaxConnection = MaxConnections;
|
||||
RetVal->AsyncSockets = (void**)malloc(MaxConnections * sizeof(void*));
|
||||
if (RetVal->AsyncSockets == NULL) { free(RetVal); ILIBMARKPOSITION(253); return NULL; }
|
||||
RetVal->portNumber = (unsigned short)PortNumber;
|
||||
RetVal->loopbackFlag = loopbackFlag;
|
||||
RetVal->initialPortNumber = PortNumber;
|
||||
|
||||
// Get our listening socket
|
||||
if ((RetVal->ListenSocket = socket(localif.sin6_family, SOCK_STREAM, IPPROTO_TCP)) == -1) { free(RetVal->AsyncSockets); free(RetVal); return 0; }
|
||||
|
||||
// Setup the IPv6 & IPv4 support on same socket
|
||||
if (localif.sin6_family == AF_INET6) if (setsockopt(RetVal->ListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&off, sizeof(off)) != 0) ILIBCRITICALERREXIT(253);
|
||||
|
||||
#ifdef SO_NOSIGPIPE
|
||||
setsockopt(RetVal->ListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&ra, sizeof(int)); // Turn off SIGPIPE if writing to disconnected socket
|
||||
#endif
|
||||
|
||||
#if defined(WIN32)
|
||||
// On Windows. Lets make sure no one else can bind to this addr/port. This stops socket hijacking (not a problem on Linux).
|
||||
if (setsockopt(RetVal->ListenSocket, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char*)&ra, sizeof(int)) != 0) ILIBCRITICALERREXIT(253);
|
||||
#else
|
||||
// On Linux. Setting the re-use on a TCP socket allows reuse of the socket even in timeout state. Allows for fast stop/start (Not a problem on Windows).
|
||||
if (setsockopt(RetVal->ListenSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&ra, sizeof(int)) != 0) ILIBCRITICALERREXIT(253);
|
||||
#endif
|
||||
|
||||
// Bind the socket
|
||||
#if defined(WIN32)
|
||||
if (bind(RetVal->ListenSocket, (struct sockaddr*)&localif, INET_SOCKADDR_LENGTH(localif.sin6_family)) != 0) { closesocket(RetVal->ListenSocket); free(RetVal->AsyncSockets); free(RetVal); return 0; }
|
||||
#else
|
||||
if (bind(RetVal->ListenSocket, (struct sockaddr*)&localif, INET_SOCKADDR_LENGTH(localif.sin6_family)) != 0) { close(RetVal->ListenSocket); free(RetVal->AsyncSockets); free(RetVal); return 0; }
|
||||
#endif
|
||||
|
||||
// Fetch the local port number
|
||||
#if defined(WINSOCK2)
|
||||
getsockname(RetVal->ListenSocket, (struct sockaddr*)&localAddress, (int*)&receivingAddressLength);
|
||||
#else
|
||||
getsockname(RetVal->ListenSocket, (struct sockaddr*)&localAddress, (socklen_t*)&receivingAddressLength);
|
||||
#endif
|
||||
if (localAddress.sin6_family == AF_INET6) RetVal->portNumber = ntohs(localAddress.sin6_port); else RetVal->portNumber = ntohs(((struct sockaddr_in*)&localAddress)->sin_port);
|
||||
|
||||
// Create our socket pool
|
||||
for(i = 0; i < MaxConnections; ++i)
|
||||
{
|
||||
RetVal->AsyncSockets[i] = ILibCreateAsyncSocketModuleWithMemory(Chain, initialBufferSize, &ILibAsyncServerSocket_OnData, &ILibAsyncServerSocket_OnConnectSink, &ILibAsyncServerSocket_OnDisconnectSink, &ILibAsyncServerSocket_OnSendOKSink, SessionUserMappedMemorySize);
|
||||
//
|
||||
// We want to know about any buffer reallocations, because anything above us may want to know
|
||||
//
|
||||
ILibAsyncSocket_SetReAllocateNotificationCallback(RetVal->AsyncSockets[i], &ILibAsyncServerSocket_OnBufferReAllocated);
|
||||
}
|
||||
ILibAddToChain(Chain, RetVal);
|
||||
|
||||
return(RetVal);
|
||||
}
|
||||
|
||||
/*! \fn ILibAsyncServerSocket_GetPortNumber(ILibAsyncServerSocket_ServerModule ServerSocketModule)
|
||||
\brief Returns the port number the server is bound to
|
||||
\param ServerSocketModule The ILibAsyncServer to query
|
||||
\returns The listening port number
|
||||
*/
|
||||
unsigned short ILibAsyncServerSocket_GetPortNumber(ILibAsyncServerSocket_ServerModule ServerSocketModule)
|
||||
{
|
||||
return(((struct ILibAsyncServerSocketModule*)ServerSocketModule)->portNumber);
|
||||
}
|
155
MicroLMS/microstack/ILibAsyncServerSocket.h
Normal file
155
MicroLMS/microstack/ILibAsyncServerSocket.h
Normal file
@@ -0,0 +1,155 @@
|
||||
/* 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 ___ILibAsyncServerSocket___
|
||||
#define ___ILibAsyncServerSocket___
|
||||
|
||||
/*! \file ILibAsyncServerSocket.h
|
||||
\brief MicroStack APIs for TCP Server Functionality
|
||||
*/
|
||||
|
||||
/*! \defgroup ILibAsyncServerSocket ILibAsyncServerSocket Module
|
||||
\{
|
||||
*/
|
||||
|
||||
#if defined(WIN32)
|
||||
#include <STDDEF.H>
|
||||
#elif defined(_POSIX)
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
#include "ILibAsyncSocket.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*! \typedef ILibAsyncServerSocket_ServerModule
|
||||
\brief The handle for an ILibAsyncServerSocket module
|
||||
*/
|
||||
typedef void* ILibAsyncServerSocket_ServerModule;
|
||||
|
||||
/*! \typedef ILibAsyncServerSocket_ConnectionToken
|
||||
\brief Connection state, for a connected session
|
||||
*/
|
||||
typedef ILibAsyncSocket_SocketModule ILibAsyncServerSocket_ConnectionToken;
|
||||
|
||||
/*! \typedef ILibAsyncServerSocket_BufferReAllocated
|
||||
\brief BufferReAllocation Handler
|
||||
\param AsyncServerSocketToken The ILibAsyncServerSocket token
|
||||
\param ConnectionToken The ILibAsyncServerSocket_Connection token
|
||||
\param user The User object
|
||||
\param newOffset The buffer has shifted by this offset
|
||||
*/
|
||||
typedef void (*ILibAsyncServerSocket_BufferReAllocated)(ILibAsyncServerSocket_ServerModule AsyncServerSocketToken, ILibAsyncServerSocket_ConnectionToken ConnectionToken, void *user, ptrdiff_t newOffset);
|
||||
void ILibAsyncServerSocket_SetReAllocateNotificationCallback(ILibAsyncServerSocket_ServerModule AsyncServerSocketToken, ILibAsyncServerSocket_ConnectionToken ConnectionToken, ILibAsyncServerSocket_BufferReAllocated Callback);
|
||||
|
||||
/*! \typedef ILibAsyncServerSocket_OnInterrupt
|
||||
\brief Handler for when a session was interrupted by a call to ILibStopChain
|
||||
\param AsyncServerSocketModule The parent ILibAsyncServerSocket_ServerModule
|
||||
\param ConnectionToken The connection state for this session
|
||||
\param user
|
||||
*/
|
||||
typedef void (*ILibAsyncServerSocket_OnInterrupt)(ILibAsyncServerSocket_ServerModule AsyncServerSocketModule, ILibAsyncServerSocket_ConnectionToken ConnectionToken, void *user);
|
||||
/*! \typedef ILibAsyncServerSocket_OnReceive
|
||||
\brief Handler for when data is received
|
||||
\par
|
||||
<B>Note on memory handling:</B>
|
||||
When you process the received buffer, you must advance \a p_beginPointer the number of bytes that you
|
||||
have processed. If \a p_beginPointer does not equal \a endPointer when this method completes,
|
||||
the system will continue to reclaim any memory that has already been processed, and call this method again
|
||||
until no more memory has been processed. If no memory has been processed, and more data has been received
|
||||
on the network, the buffer will be automatically grown (according to a specific alogrythm), to accomodate any new data.
|
||||
\param AsyncServerSocketModule The parent ILibAsyncServerSocket_ServerModule
|
||||
\param ConnectionToken The connection state for this session
|
||||
\param buffer The data that was received
|
||||
\param[in,out] p_beginPointer The start index of the data that was received
|
||||
\param endPointer The end index of the data that was received
|
||||
\param[in,out] OnInterrupt Set this pointer to receive notification if this session is interrupted
|
||||
\param[in,out] user Set a custom user object
|
||||
\param[out] PAUSE Flag to indicate if the system should continue reading data off the network
|
||||
*/
|
||||
typedef void (*ILibAsyncServerSocket_OnReceive)(ILibAsyncServerSocket_ServerModule AsyncServerSocketModule, ILibAsyncServerSocket_ConnectionToken ConnectionToken, char* buffer, int *p_beginPointer, int endPointer, ILibAsyncServerSocket_OnInterrupt *OnInterrupt, void **user, int *PAUSE);
|
||||
/*! \typedef ILibAsyncServerSocket_OnConnect
|
||||
\brief Handler for when a connection is made
|
||||
\param AsyncServerSocketModule The parent ILibAsyncServerSocket_ServerModule
|
||||
\param ConnectionToken The connection state for this session
|
||||
\param[in,out] user Set a user object to associate with this connection
|
||||
*/
|
||||
typedef void (*ILibAsyncServerSocket_OnConnect)(ILibAsyncServerSocket_ServerModule AsyncServerSocketModule, ILibAsyncServerSocket_ConnectionToken ConnectionToken, void **user);
|
||||
/*! \typedef ILibAsyncServerSocket_OnDisconnect
|
||||
\brief Handler for when a connection is terminated normally
|
||||
\param AsyncServerSocketModule The parent ILibAsyncServerSocket_ServerModule
|
||||
\param ConnectionToken The connection state for this session
|
||||
\param user User object that was associated with this connection
|
||||
*/
|
||||
typedef void (*ILibAsyncServerSocket_OnDisconnect)(ILibAsyncServerSocket_ServerModule AsyncServerSocketModule, ILibAsyncServerSocket_ConnectionToken ConnectionToken, void *user);
|
||||
/*! \typedef ILibAsyncServerSocket_OnSendOK
|
||||
\brief Handler for when pending send operations have completed
|
||||
\par
|
||||
This handler will only be called if a call to \a ILibAsyncServerSocket_Send returned a value greater
|
||||
than 0, which indicates that not all of the data could be sent.
|
||||
\param AsyncServerSocketModule The parent ILibAsyncServerSocket_ServerModule
|
||||
\param ConnectionToken The connection state for this session
|
||||
\param user User object that was associated with this connection
|
||||
*/
|
||||
typedef void (*ILibAsyncServerSocket_OnSendOK)(ILibAsyncServerSocket_ServerModule AsyncServerSocketModule, ILibAsyncServerSocket_ConnectionToken ConnectionToken, void *user);
|
||||
|
||||
extern const int ILibMemory_ASYNCSERVERSOCKET_CONTAINERSIZE;
|
||||
|
||||
#define ILibCreateAsyncServerSocketModule(Chain, MaxConnections, PortNumber, initialBufferSize, loopbackFlag, OnConnect, OnDisconnect, OnReceive, OnInterrupt, OnSendOK) ILibCreateAsyncServerSocketModuleWithMemory(Chain, MaxConnections, PortNumber, initialBufferSize, loopbackFlag, OnConnect, OnDisconnect, OnReceive, OnInterrupt, OnSendOK, 0, 0)
|
||||
ILibAsyncServerSocket_ServerModule ILibCreateAsyncServerSocketModuleWithMemory(void *Chain, int MaxConnections, unsigned short PortNumber, int initialBufferSize, int loopbackFlag, ILibAsyncServerSocket_OnConnect OnConnect, ILibAsyncServerSocket_OnDisconnect OnDisconnect, ILibAsyncServerSocket_OnReceive OnReceive, ILibAsyncServerSocket_OnInterrupt OnInterrupt, ILibAsyncServerSocket_OnSendOK OnSendOK, int ServerUserMappedMemorySize, int SessionUserMappedMemorySize);
|
||||
|
||||
void *ILibAsyncServerSocket_GetTag(ILibAsyncServerSocket_ServerModule ILibAsyncSocketModule);
|
||||
void ILibAsyncServerSocket_SetTag(ILibAsyncServerSocket_ServerModule ILibAsyncSocketModule, void *user);
|
||||
int ILibAsyncServerSocket_GetTag2(ILibAsyncServerSocket_ServerModule ILibAsyncSocketModule);
|
||||
void ILibAsyncServerSocket_SetTag2(ILibAsyncServerSocket_ServerModule ILibAsyncSocketModule, int user);
|
||||
|
||||
void ILibAsyncServerSocket_StopListening(ILibAsyncServerSocket_ServerModule module);
|
||||
void ILibAsyncServerSocket_ResumeListening(ILibAsyncServerSocket_ServerModule module);
|
||||
|
||||
unsigned short ILibAsyncServerSocket_GetPortNumber(ILibAsyncServerSocket_ServerModule ServerSocketModule);
|
||||
|
||||
/*! \def ILibAsyncServerSocket_Send
|
||||
\brief Sends data onto the TCP stream
|
||||
\param ServerSocketModule The parent ILibAsyncServerSocket_ServerModule
|
||||
\param ConnectionToken The connection state for this session
|
||||
\param buffer The data to be sent
|
||||
\param bufferLength The length of \a buffer
|
||||
\param UserFreeBuffer The \a ILibAsyncSocket_MemoryOwnership enumeration, that identifies how the memory pointer to by \a buffer is to be handled
|
||||
\returns \a ILibAsyncSocket_SendStatus indicating the send status
|
||||
*/
|
||||
#define ILibAsyncServerSocket_Send(ServerSocketModule, ConnectionToken, buffer, bufferLength, UserFreeBuffer) ILibAsyncSocket_Send(ConnectionToken, buffer, bufferLength, UserFreeBuffer)
|
||||
|
||||
/*! \def ILibAsyncServerSocket_Disconnect
|
||||
\brief Disconnects a TCP stream
|
||||
\param ServerSocketModule The parent ILibAsyncServerSocket_ServerModule
|
||||
\param ConnectionToken The connection state for this session
|
||||
*/
|
||||
#define ILibAsyncServerSocket_Disconnect(ServerSocketModule, ConnectionToken) ILibAsyncSocket_Disconnect(ConnectionToken)
|
||||
/*! \def ILibAsyncServerSocket_GetPendingBytesToSend
|
||||
\brief Gets the outstanding number of bytes to be sent
|
||||
*/
|
||||
#define ILibAsyncServerSocket_GetPendingBytesToSend(ServerSocketModule, ConnectionToken) ILibAsyncSocket_GetPendingBytesToSend(ConnectionToken)
|
||||
/*! \def ILibAsyncServerSocket_GetTotalBytesSent
|
||||
\brief Gets the total number of bytes that have been sent
|
||||
\param ServerSocketModule The parent ILibAsyncServerSocket_ServerModule
|
||||
\param ConnectionToken The connection state for this session
|
||||
*/
|
||||
#define ILibAsyncServerSocket_GetTotalBytesSent(ServerSocketModule, ConnectionToken) ILibAsyncSocket_GetTotalBytesSent(ConnectionToken)
|
||||
/*! \def ILibAsyncServerSocket_ResetTotalBytesSent
|
||||
\brief Resets the total bytes sent counter
|
||||
\param ServerSocketModule The parent ILibAsyncServerSocket_ServerModule
|
||||
\param ConnectionToken The connection state for this session
|
||||
*/
|
||||
#define ILibAsyncServerSocket_ResetTotalBytesSent(ServerSocketModule, ConnectionToken) ILibAsyncSocket_ResetTotalBytesSent(ConnectionToken)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
1677
MicroLMS/microstack/ILibAsyncSocket.c
Normal file
1677
MicroLMS/microstack/ILibAsyncSocket.c
Normal file
File diff suppressed because it is too large
Load Diff
195
MicroLMS/microstack/ILibAsyncSocket.h
Normal file
195
MicroLMS/microstack/ILibAsyncSocket.h
Normal file
@@ -0,0 +1,195 @@
|
||||
/* 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 ___ILibAsyncSocket___
|
||||
#define ___ILibAsyncSocket___
|
||||
|
||||
/*! \file ILibAsyncSocket.h
|
||||
\brief MicroStack APIs for TCP Client Functionality
|
||||
*/
|
||||
|
||||
/*! \defgroup ILibAsyncSocket ILibAsyncSocket Module
|
||||
\{
|
||||
*/
|
||||
|
||||
#if defined(WIN32)
|
||||
#include <STDDEF.H>
|
||||
#elif defined(_POSIX)
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
//#include "ssl.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*! \def MEMORYCHUNKSIZE
|
||||
\brief Incrementally grow the buffer by this amount of bytes
|
||||
*/
|
||||
#define MEMORYCHUNKSIZE 4096
|
||||
|
||||
#define ILibTransports_AsyncSocket 0x40
|
||||
|
||||
typedef enum ILibAsyncSocket_SendStatus
|
||||
{
|
||||
ILibAsyncSocket_ALL_DATA_SENT = 1, /*!< All of the data has already been sent */
|
||||
ILibAsyncSocket_NOT_ALL_DATA_SENT_YET = 0, /*!< Not all of the data could be sent, but is queued to be sent as soon as possible */
|
||||
ILibAsyncSocket_SEND_ON_CLOSED_SOCKET_ERROR = -4 /*!< A send operation was attmepted on a closed socket */
|
||||
}ILibAsyncSocket_SendStatus;
|
||||
|
||||
/*! \enum ILibAsyncSocket_MemoryOwnership
|
||||
\brief Enumeration values for Memory Ownership of variables
|
||||
*/
|
||||
typedef enum ILibAsyncSocket_MemoryOwnership
|
||||
{
|
||||
ILibAsyncSocket_MemoryOwnership_CHAIN = 0, /*!< The Microstack will own this memory, and free it when it is done with it */
|
||||
ILibAsyncSocket_MemoryOwnership_STATIC = 1, /*!< This memory is static, so the Microstack will not free it, and assume it will not go away, so it won't copy it either */
|
||||
ILibAsyncSocket_MemoryOwnership_USER = 2 /*!< The Microstack doesn't own this memory, so if necessary the memory will be copied */
|
||||
}ILibAsyncSocket_MemoryOwnership;
|
||||
|
||||
/*! \typedef ILibAsyncSocket_SocketModule
|
||||
\brief The handle for an ILibAsyncSocket module
|
||||
*/
|
||||
typedef void* ILibAsyncSocket_SocketModule;
|
||||
/*! \typedef ILibAsyncSocket_OnInterrupt
|
||||
\brief Handler for when a session was interrupted by a call to ILibStopChain
|
||||
\param socketModule The \a ILibAsyncSocket_SocketModule that was interrupted
|
||||
\param user The user object that was associated with this connection
|
||||
*/
|
||||
|
||||
//typedef void(*ILibAsyncSocket_OnReplaceSocket)(ILibAsyncSocket_SocketModule socketModule, void *user);
|
||||
typedef void(*ILibAsyncSocket_OnBufferSizeExceeded)(ILibAsyncSocket_SocketModule socketModule, void *user);
|
||||
|
||||
typedef void(*ILibAsyncSocket_OnInterrupt)(ILibAsyncSocket_SocketModule socketModule, void *user);
|
||||
/*! \typedef ILibAsyncSocket_OnData
|
||||
\brief Handler for when data is received
|
||||
\par
|
||||
<B>Note on memory handling:</B>
|
||||
When you process the received buffer, you must advance \a p_beginPointer the number of bytes that you
|
||||
have processed. If \a p_beginPointer does not equal \a endPointer when this method completes,
|
||||
the system will continue to reclaim any memory that has already been processed, and call this method again
|
||||
until no more memory has been processed. If no memory has been processed, and more data has been received
|
||||
on the network, the buffer will be automatically grown (according to a specific alogrythm), to accomodate any new data.
|
||||
\param socketModule The \a ILibAsyncSocket_SocketModule that received data
|
||||
\param buffer The data that was received
|
||||
\param[in,out] p_beginPointer The start index of the data that was received
|
||||
\param endPointer The end index of the data that was received
|
||||
\param[in,out] OnInterrupt Set this pointer to receive notification if this session is interrupted
|
||||
\param[in,out] user Set a custom user object
|
||||
\param[out] PAUSE Flag to indicate if the system should continue reading data off the network
|
||||
*/
|
||||
typedef void(*ILibAsyncSocket_OnData)(ILibAsyncSocket_SocketModule socketModule, char* buffer, int *p_beginPointer, int endPointer,ILibAsyncSocket_OnInterrupt* OnInterrupt, void **user, int *PAUSE);
|
||||
/*! \typedef ILibAsyncSocket_OnConnect
|
||||
\brief Handler for when a connection is made
|
||||
\param socketModule The \a ILibAsyncSocket_SocketModule that was connected
|
||||
\param user The user object that was associated with this object
|
||||
*/
|
||||
typedef void(*ILibAsyncSocket_OnConnect)(ILibAsyncSocket_SocketModule socketModule, int Connected, void *user);
|
||||
/*! \typedef ILibAsyncSocket_OnDisconnect
|
||||
\brief Handler for when a connection is terminated normally
|
||||
\param socketModule The \a ILibAsyncSocket_SocketModule that was disconnected
|
||||
\param user User object that was associated with this connection
|
||||
*/
|
||||
typedef void(*ILibAsyncSocket_OnDisconnect)(ILibAsyncSocket_SocketModule socketModule, void *user);
|
||||
/*! \typedef ILibAsyncSocket_OnSendOK
|
||||
\brief Handler for when pending send operations have completed
|
||||
\par
|
||||
This handler will only be called if a call to \a ILibAsyncSocket_Send returned a value greater
|
||||
than 0, which indicates that not all of the data could be sent.
|
||||
\param socketModule The \a ILibAsyncSocket_SocketModule whos pending sends have completed
|
||||
\param user User object that was associated with this connection
|
||||
*/
|
||||
typedef void(*ILibAsyncSocket_OnSendOK)(ILibAsyncSocket_SocketModule socketModule, void *user);
|
||||
/*! \typedef ILibAsyncSocket_OnBufferReAllocated
|
||||
\brief Handler for when the internal data buffer has been resized.
|
||||
\par
|
||||
<B>Note:</B> This is only useful if you are storing pointer values into the buffer supplied in \a ILibAsyncSocket_OnData.
|
||||
\param AsyncSocketToken The \a ILibAsyncSocket_SocketModule whos buffer was resized
|
||||
\param user The user object that was associated with this connection
|
||||
\param newOffset The new offset differential. Simply add this value to your existing pointers, to obtain the correct pointer into the resized buffer.
|
||||
*/
|
||||
typedef void(*ILibAsyncSocket_OnBufferReAllocated)(ILibAsyncSocket_SocketModule AsyncSocketToken, void *user, ptrdiff_t newOffset);
|
||||
|
||||
/*! \defgroup TLSGroup TLS Related Methods
|
||||
* @{
|
||||
*/
|
||||
/*! @} */
|
||||
|
||||
extern const int ILibMemory_ASYNCSOCKET_CONTAINERSIZE;
|
||||
|
||||
void ILibAsyncSocket_SetReAllocateNotificationCallback(ILibAsyncSocket_SocketModule AsyncSocketToken, ILibAsyncSocket_OnBufferReAllocated Callback);
|
||||
void *ILibAsyncSocket_GetUser(ILibAsyncSocket_SocketModule socketModule);
|
||||
void ILibAsyncSocket_SetUser(ILibAsyncSocket_SocketModule socketModule, void* user);
|
||||
void *ILibAsyncSocket_GetUser2(ILibAsyncSocket_SocketModule socketModule);
|
||||
void ILibAsyncSocket_SetUser2(ILibAsyncSocket_SocketModule socketModule, void* user);
|
||||
int ILibAsyncSocket_GetUser3(ILibAsyncSocket_SocketModule socketModule);
|
||||
void ILibAsyncSocket_SetUser3(ILibAsyncSocket_SocketModule socketModule, int user);
|
||||
void ILibAsyncSocket_UpdateOnData(ILibAsyncSocket_SocketModule module, ILibAsyncSocket_OnData OnData);
|
||||
|
||||
#define ILibCreateAsyncSocketModule(Chain, initialBufferSize, OnData, OnConnect, OnDisconnect, OnSendOK) ILibCreateAsyncSocketModuleWithMemory(Chain, initialBufferSize, OnData, OnConnect, OnDisconnect, OnSendOK, 0)
|
||||
ILibAsyncSocket_SocketModule ILibCreateAsyncSocketModuleWithMemory(void *Chain, int initialBufferSize, ILibAsyncSocket_OnData OnData, ILibAsyncSocket_OnConnect OnConnect, ILibAsyncSocket_OnDisconnect OnDisconnect, ILibAsyncSocket_OnSendOK OnSendOK, int UserMappedMemorySize);
|
||||
|
||||
void *ILibAsyncSocket_GetSocket(ILibAsyncSocket_SocketModule module);
|
||||
void ILibAsyncSocket_Shutdown(ILibAsyncSocket_SocketModule module);
|
||||
|
||||
unsigned int ILibAsyncSocket_GetPendingBytesToSend(ILibAsyncSocket_SocketModule socketModule);
|
||||
unsigned int ILibAsyncSocket_GetTotalBytesSent(ILibAsyncSocket_SocketModule socketModule);
|
||||
void ILibAsyncSocket_ResetTotalBytesSent(ILibAsyncSocket_SocketModule socketModule);
|
||||
|
||||
void ILibAsyncSocket_ConnectTo(void* socketModule, struct sockaddr *localInterface, struct sockaddr *remoteAddress, ILibAsyncSocket_OnInterrupt InterruptPtr, void *user);
|
||||
|
||||
#ifdef MICROSTACK_PROXY
|
||||
void ILibAsyncSocket_ConnectToProxy(void* socketModule, struct sockaddr *localInterface, struct sockaddr *remoteAddress, struct sockaddr *proxyAddress, char* proxyUser, char* proxyPass, ILibAsyncSocket_OnInterrupt InterruptPtr, void *user);
|
||||
#endif
|
||||
|
||||
enum ILibAsyncSocket_SendStatus ILibAsyncSocket_SendTo(ILibAsyncSocket_SocketModule socketModule, char* buffer, int length, struct sockaddr *remoteAddress, enum ILibAsyncSocket_MemoryOwnership UserFree);
|
||||
|
||||
/*! \def ILibAsyncSocket_Send
|
||||
\brief Sends data onto the TCP stream
|
||||
\param socketModule The \a ILibAsyncSocket_SocketModule to send data on
|
||||
\param buffer The data to be sent
|
||||
\param length The length of \a buffer
|
||||
\param UserFree The \a ILibAsyncSocket_MemoryOwnership enumeration, that identifies how the memory pointer to by \a buffer is to be handled
|
||||
\returns \a ILibAsyncSocket_SendStatus indicating the send status
|
||||
*/
|
||||
#define ILibAsyncSocket_Send(socketModule, buffer, length, UserFree) ILibAsyncSocket_SendTo(socketModule, buffer, length, NULL, UserFree)
|
||||
void ILibAsyncSocket_Disconnect(ILibAsyncSocket_SocketModule socketModule);
|
||||
void ILibAsyncSocket_GetBuffer(ILibAsyncSocket_SocketModule socketModule, char **buffer, int *BeginPointer, int *EndPointer);
|
||||
|
||||
#if defined(WIN32)
|
||||
void ILibAsyncSocket_UseThisSocket(ILibAsyncSocket_SocketModule socketModule, SOCKET UseThisSocket, ILibAsyncSocket_OnInterrupt InterruptPtr, void *user);
|
||||
#elif defined(_POSIX)
|
||||
void ILibAsyncSocket_UseThisSocket(ILibAsyncSocket_SocketModule socketModule, int UseThisSocket, ILibAsyncSocket_OnInterrupt InterruptPtr, void *user);
|
||||
#endif
|
||||
|
||||
|
||||
void ILibAsyncSocket_SetRemoteAddress(ILibAsyncSocket_SocketModule socketModule, struct sockaddr *remoteAddress);
|
||||
void ILibAsyncSocket_SetLocalInterface(ILibAsyncSocket_SocketModule module, struct sockaddr *localAddress);
|
||||
|
||||
int ILibAsyncSocket_IsFree(ILibAsyncSocket_SocketModule socketModule);
|
||||
int ILibAsyncSocket_IsConnected(ILibAsyncSocket_SocketModule socketModule);
|
||||
int ILibAsyncSocket_GetLocalInterface(ILibAsyncSocket_SocketModule socketModule, struct sockaddr *localAddress);
|
||||
int ILibAsyncSocket_GetRemoteInterface(ILibAsyncSocket_SocketModule socketModule, struct sockaddr *remoteAddress);
|
||||
unsigned short ILibAsyncSocket_GetLocalPort(ILibAsyncSocket_SocketModule socketModule);
|
||||
|
||||
void ILibAsyncSocket_Resume(ILibAsyncSocket_SocketModule socketModule);
|
||||
void ILibAsyncSocket_Pause(ILibAsyncSocket_SocketModule socketModule);
|
||||
int ILibAsyncSocket_WasClosedBecauseBufferSizeExceeded(ILibAsyncSocket_SocketModule socketModule);
|
||||
void ILibAsyncSocket_SetMaximumBufferSize(ILibAsyncSocket_SocketModule module, int maxSize, ILibAsyncSocket_OnBufferSizeExceeded OnBufferSizeExceededCallback, void *user);
|
||||
void ILibAsyncSocket_SetSendOK(ILibAsyncSocket_SocketModule module, ILibAsyncSocket_OnSendOK OnSendOK);
|
||||
int ILibAsyncSocket_IsIPv6LinkLocal(struct sockaddr *LocalAddress);
|
||||
int ILibAsyncSocket_IsModuleIPv6LinkLocal(ILibAsyncSocket_SocketModule module);
|
||||
|
||||
typedef void(*ILibAsyncSocket_TimeoutHandler)(ILibAsyncSocket_SocketModule module, void *user);
|
||||
void ILibAsyncSocket_SetTimeout(ILibAsyncSocket_SocketModule module, int timeoutSeconds, ILibAsyncSocket_TimeoutHandler timeoutHandler);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
834
MicroLMS/microstack/ILibLMS.c
Normal file
834
MicroLMS/microstack/ILibLMS.c
Normal file
@@ -0,0 +1,834 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
Real LMS code can be found here: http://software.intel.com/en-us/articles/download-the-latest-intel-amt-open-source-drivers
|
||||
*/
|
||||
|
||||
#if !defined(_NOHECI)
|
||||
|
||||
#if defined(WIN32) && !defined(_MINCORE)
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include <stdlib.h>
|
||||
#include <crtdbg.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#if defined(WINSOCK2)
|
||||
#include <winsock2.h>
|
||||
#include <ws2ipdef.h>
|
||||
#elif defined(WINSOCK1)
|
||||
#include <winsock.h>
|
||||
#include <wininet.h>
|
||||
#endif
|
||||
|
||||
#include "ILibParsers.h"
|
||||
#include "ILibAsyncSocket.h"
|
||||
#include "ILibAsyncServerSocket.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#include "../heci/heciwin.h"
|
||||
#include "WinBase.h"
|
||||
#endif
|
||||
#ifdef _POSIX
|
||||
#include "../heci/HECILinux.h"
|
||||
#define UNREFERENCED_PARAMETER(P) (P)
|
||||
#endif
|
||||
#include "../heci/PTHICommand.h"
|
||||
#include "../heci/LMEConnection.h"
|
||||
|
||||
#define INET_SOCKADDR_LENGTH(x) ((x==AF_INET6?sizeof(struct sockaddr_in6):sizeof(struct sockaddr_in)))
|
||||
#define LMS_MAX_CONNECTIONS 16 // Maximum is 32
|
||||
#define LMS_MAX_SESSIONS 32
|
||||
// #define _DEBUGLMS
|
||||
#ifdef _DEBUGLMS
|
||||
#define LMSDEBUG(...) printf(__VA_ARGS__);
|
||||
#else
|
||||
#define LMSDEBUG(...)
|
||||
#endif
|
||||
|
||||
char * g_SelfLMSDir=NULL;
|
||||
int LastId = 2;
|
||||
|
||||
struct ILibLMS_StateModule* IlibExternLMS = NULL; // Glocal pointer to the LMS module. Since we can only have one of these modules running, a global pointer is sometimes useful.
|
||||
void ILibLMS_SetupConnection(struct ILibLMS_StateModule* module, int i);
|
||||
void ILibLMS_LaunchHoldingSessions(struct ILibLMS_StateModule* module);
|
||||
|
||||
// Each LMS session can be in one of these states.
|
||||
enum LME_CHANNEL_STATUS {
|
||||
LME_CS_FREE = 0, // The session slot is free, can be used at any time.
|
||||
LME_CS_PENDING_CONNECT = 1, // A connection as been made to LMS and a notice has been send to Intel AMT asking for a CHANNEL OPEN.
|
||||
LME_CS_CONNECTED = 2, // Intel AMT confirmed the connection and data can flow in both directions.
|
||||
LME_CS_PENDING_LMS_DISCONNECT = 3, // The connection to LMS was disconnected, Intel AMT has been notified and we are waitting for Intel AMT confirmation.
|
||||
LME_CS_PENDING_AMT_DISCONNECT = 4, // Intel AMT decided to close the connection. We are disconnecting the LMS TCP connection.
|
||||
LME_CS_HOLDING = 5, // We got too much data from the LMS TCP connection, more than Intel AMT can handle. We are holding the connection until AMT can handle more.
|
||||
LME_CS_CONNECTION_WAIT = 6 // A TCP connection to LMS was made, but there all LMS connections are currently busy. Waitting for one to free up.
|
||||
};
|
||||
|
||||
// This is the structure for a session
|
||||
struct LMEChannel
|
||||
{
|
||||
int ourid; // The iddentifier of this channel on our side, this is the same as the index in the "Channel Sessions[LMS_MAX_SESSIONS];" array below.
|
||||
int amtid; // The Intel AMT identifier for this channel.
|
||||
enum LME_CHANNEL_STATUS status; // Current status of the channel.
|
||||
int sockettype; // Type of connected socket: 0 = TCP, 1 = WebSocket
|
||||
void* socketmodule; // The microstack associated with the LMS connection.
|
||||
int txwindow; // Transmit window.
|
||||
int rxwindow; // Receive window.
|
||||
unsigned short localport; // The Intel AMT connection port.
|
||||
int errorcount; // Open channel error count.
|
||||
char* pending; // Buffer pointing to pending data that needs to be sent to Intel AMT, used for websocket only.
|
||||
int pendingcount; // Buffer pointing to pending data size that needs to be sent to Intel AMT, used for websocket only.
|
||||
int pendingptr; // Pointer to start of the pending buffer.
|
||||
};
|
||||
|
||||
enum LME_VERSION_HANDSHAKING {
|
||||
LME_NOT_INITIATED,
|
||||
LME_INITIATED,
|
||||
LME_AGREED
|
||||
};
|
||||
|
||||
enum LME_SERVICE_STATUS {
|
||||
LME_NOT_STARTED,
|
||||
LME_STARTED
|
||||
};
|
||||
|
||||
// This is the Intel AMT LMS chain module structure
|
||||
struct ILibLMS_StateModule
|
||||
{
|
||||
ILibChain_Link ChainLink;
|
||||
void *Server1; // Microstack TCP server for port 16992
|
||||
void *Server2; // Microstack TCP server for port 16993
|
||||
void *ControlSocket; // Pointer to the LMS control web socket, NULL if not connected.
|
||||
|
||||
struct LMEConnection MeConnection; // The MEI connection structure
|
||||
struct LMEChannel Sessions[LMS_MAX_SESSIONS]; // List of sessions
|
||||
//ILibWebServer_ServerToken WebServer; // LMS Web Server
|
||||
enum LME_VERSION_HANDSHAKING handshakingStatus;
|
||||
enum LME_SERVICE_STATUS pfwdService;
|
||||
unsigned int AmtProtVersionMajor; // Intel AMT MEI major version
|
||||
unsigned int AmtProtVersionMinor; // Intel AMT MEI minor version
|
||||
sem_t Lock; // Global lock, this is needed because MEI listener is a different thread from the microstack thread
|
||||
};
|
||||
|
||||
/*
|
||||
// Convert a block of data to HEX
|
||||
// The "out" must have (len*2)+1 free space.
|
||||
char utils_HexTable[16] = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' };
|
||||
char* __fastcall util_tohex(char* data, int len, char* out)
|
||||
{
|
||||
int i;
|
||||
char *p = out;
|
||||
if (data == NULL || len == 0) { *p = 0; return NULL; }
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
*(p++) = utils_HexTable[((unsigned char)data[i]) >> 4];
|
||||
*(p++) = utils_HexTable[((unsigned char)data[i]) & 0x0F];
|
||||
}
|
||||
*p = 0;
|
||||
return out;
|
||||
}
|
||||
*/
|
||||
|
||||
int GetFreeSlot(struct ILibLMS_StateModule* module){
|
||||
int i;
|
||||
int cur = LastId;
|
||||
// Look for an empty session
|
||||
for (i = 0; i < LMS_MAX_SESSIONS-3; i++) {
|
||||
cur++;
|
||||
if (cur >= LMS_MAX_SESSIONS){
|
||||
cur = 3;
|
||||
}
|
||||
if (module->Sessions[cur].status == LME_CS_FREE) {
|
||||
LastId = cur;
|
||||
return cur;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
//int GetFreeSlot(struct ILibLMS_StateModule* module){
|
||||
// int i;
|
||||
// for (i = 0; i < LMS_MAX_SESSIONS - 3; i++) {
|
||||
// if (cur >= LMS_MAX_SESSIONS){
|
||||
// cur = 3;
|
||||
// }
|
||||
// if (module->Sessions[cur].status == LME_CS_FREE) {
|
||||
// LastId = cur;
|
||||
// return cur;
|
||||
// }
|
||||
// }
|
||||
// return -1;
|
||||
//}
|
||||
|
||||
// This function is called each time a MEI message is received from Intel AMT
|
||||
void ILibLMS_MEICallback(struct LMEConnection* lmemodule, void *param, void *rxBuffer, unsigned int len)
|
||||
{
|
||||
struct ILibLMS_StateModule* module = (struct ILibLMS_StateModule*)param;
|
||||
int disconnects = 0; // This is a counter of how many sessions are freed up. We use this at the end to place HOLDING sessions into free slots.
|
||||
|
||||
//ILibAsyncServerSocket_ServerModule newModule;
|
||||
//ILibLinkedList list;
|
||||
//void* node;
|
||||
//ILibTransport* curModule;
|
||||
|
||||
// Happens when the chain is being destroyed, don't call anything chain related.
|
||||
if (rxBuffer == NULL) return;
|
||||
|
||||
sem_wait(&(module->Lock));
|
||||
LMSDEBUG("ILibLMS_MEICallback %d\r\n", ((unsigned char*)rxBuffer)[0]);
|
||||
|
||||
switch (((unsigned char*)rxBuffer)[0])
|
||||
{
|
||||
case APF_GLOBAL_REQUEST: // 80
|
||||
{
|
||||
|
||||
int request = 0;
|
||||
unsigned char *pCurrent;
|
||||
APF_GENERIC_HEADER *pHeader = (APF_GENERIC_HEADER *)rxBuffer;
|
||||
|
||||
pHeader->StringLength = ntohl(pHeader->StringLength);
|
||||
|
||||
if (pHeader->StringLength == APF_STR_SIZE_OF(APF_GLOBAL_REQUEST_STR_TCP_FORWARD_REQUEST) && memcmp(pHeader->String, APF_GLOBAL_REQUEST_STR_TCP_FORWARD_REQUEST, APF_STR_SIZE_OF(APF_GLOBAL_REQUEST_STR_TCP_FORWARD_REQUEST)) == 0) { request = 1; }
|
||||
else if (pHeader->StringLength == APF_STR_SIZE_OF(APF_GLOBAL_REQUEST_STR_TCP_FORWARD_CANCEL_REQUEST) && memcmp(pHeader->String, APF_GLOBAL_REQUEST_STR_TCP_FORWARD_CANCEL_REQUEST, APF_STR_SIZE_OF(APF_GLOBAL_REQUEST_STR_TCP_FORWARD_CANCEL_REQUEST)) == 0) { request = 2; }
|
||||
else if (pHeader->StringLength == APF_STR_SIZE_OF(APF_GLOBAL_REQUEST_STR_UDP_SEND_TO) && memcmp(pHeader->String, APF_GLOBAL_REQUEST_STR_UDP_SEND_TO, APF_STR_SIZE_OF(APF_GLOBAL_REQUEST_STR_UDP_SEND_TO)) == 0) { request = 3; }
|
||||
|
||||
|
||||
if (request == 1 || request == 2)
|
||||
{
|
||||
int port = 0;
|
||||
unsigned int len2;
|
||||
unsigned int bytesRead = len;
|
||||
unsigned int hsize=0;
|
||||
if (request==1)
|
||||
hsize = sizeof(APF_GENERIC_HEADER) + APF_STR_SIZE_OF(APF_GLOBAL_REQUEST_STR_TCP_FORWARD_REQUEST) + sizeof(UINT8);
|
||||
else if (request==2)
|
||||
hsize = sizeof(APF_GENERIC_HEADER) + APF_STR_SIZE_OF(APF_GLOBAL_REQUEST_STR_TCP_FORWARD_CANCEL_REQUEST) + sizeof(UINT8);
|
||||
|
||||
pCurrent = (unsigned char*)rxBuffer + hsize;
|
||||
bytesRead -= hsize;
|
||||
if (bytesRead < sizeof(unsigned int)) {
|
||||
LME_Deinit(lmemodule);
|
||||
sem_post(&(module->Lock));
|
||||
return;
|
||||
}
|
||||
|
||||
len2 = ntohl(*((unsigned int *)pCurrent));
|
||||
pCurrent += sizeof(unsigned int);
|
||||
if (bytesRead < (sizeof(unsigned int) + len2 + sizeof(unsigned int))) {
|
||||
LME_Deinit(lmemodule);
|
||||
sem_post(&(module->Lock));
|
||||
return;
|
||||
}
|
||||
|
||||
// addr = (char*)pCurrent;
|
||||
pCurrent += len2;
|
||||
port = ntohl(*((unsigned int *)pCurrent));
|
||||
|
||||
if (request == 1)
|
||||
{
|
||||
//newModule = ILibCreateAsyncServerSocketModule(module->Chain, LMS_MAX_CONNECTIONS, port, 4096, 0, &ILibLMS_OnConnect, &ILibLMS_OnDisconnect, &ILibLMS_OnReceive, NULL, &ILibLMS_OnSendOK);
|
||||
//if (newModule){
|
||||
// ILibAsyncServerSocket_SetTag(newModule, module);
|
||||
// LME_TcpForwardReplySuccess(lmemodule, port);
|
||||
//}
|
||||
//else{
|
||||
// LME_TcpForwardReplyFailure(lmemodule);
|
||||
//}
|
||||
|
||||
// New forwarding request
|
||||
if (port == 16992 || port == 16993)
|
||||
LME_TcpForwardReplySuccess(lmemodule, port);
|
||||
else
|
||||
LME_TcpForwardReplyFailure(lmemodule);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Cancel a forwarding request
|
||||
|
||||
|
||||
|
||||
//list = ILibGetModuleList(module->Chain);
|
||||
//node = ILibLinkedList_GetNode_Head(list);
|
||||
//while (node != NULL){
|
||||
// curModule = (ILibTransport*)ILibLinkedList_GetDataFromNode(node);
|
||||
// if (curModule->IdentifierFlags == ILibTransports_ILibAsyncServerSocket){
|
||||
// if (ILibAsyncServerSocket_GetPortNumber(curModule)){
|
||||
// ILibAsyncServerSocket_Close(curModule);
|
||||
// }
|
||||
// }
|
||||
// node = ILibLinkedList_GetNextNode(node);
|
||||
//}
|
||||
|
||||
|
||||
LME_TcpForwardCancelReplySuccess(lmemodule);
|
||||
}
|
||||
}
|
||||
else if (request == 3)
|
||||
{
|
||||
// Send a UDP packet
|
||||
// TODO: Send UDP
|
||||
}
|
||||
else{
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
break;
|
||||
case APF_CHANNEL_OPEN: // (90) Sent by Intel AMT when a channel needs to be open from Intel AMT. This is not common, but WSMAN events are a good example of channel coming from AMT.
|
||||
{
|
||||
APF_GENERIC_HEADER *pHeader = (APF_GENERIC_HEADER *)rxBuffer;
|
||||
|
||||
if (pHeader->StringLength == APF_STR_SIZE_OF(APF_OPEN_CHANNEL_REQUEST_DIRECT) && memcmp((char*)pHeader->String, APF_OPEN_CHANNEL_REQUEST_DIRECT, APF_STR_SIZE_OF(APF_OPEN_CHANNEL_REQUEST_DIRECT)) == 0)
|
||||
{
|
||||
unsigned int len2;
|
||||
unsigned char *pCurrent;
|
||||
struct LMEChannelOpenRequestMessage channelOpenRequest;
|
||||
|
||||
if (len < sizeof(APF_GENERIC_HEADER) + ntohl(pHeader->StringLength) + 7 + (5 * sizeof(UINT32))) { LME_Deinit(lmemodule); sem_post(&(module->Lock)); return; }
|
||||
pCurrent = (unsigned char*)rxBuffer + sizeof(APF_GENERIC_HEADER) + APF_STR_SIZE_OF(APF_OPEN_CHANNEL_REQUEST_DIRECT);
|
||||
|
||||
channelOpenRequest.ChannelType = APF_CHANNEL_DIRECT;
|
||||
channelOpenRequest.SenderChannel = ntohl(*((UINT32 *)pCurrent));
|
||||
pCurrent += sizeof(UINT32);
|
||||
channelOpenRequest.InitialWindow = ntohl(*((UINT32 *)pCurrent));
|
||||
pCurrent += 2 * sizeof(UINT32);
|
||||
len2 = ntohl(*((UINT32 *)pCurrent));
|
||||
pCurrent += sizeof(UINT32);
|
||||
channelOpenRequest.Address = (char*)pCurrent;
|
||||
pCurrent += len2;
|
||||
channelOpenRequest.Port = ntohl(*((UINT32 *)pCurrent));
|
||||
pCurrent += sizeof(UINT32);
|
||||
|
||||
LME_ChannelOpenReplyFailure(lmemodule, channelOpenRequest.SenderChannel, OPEN_FAILURE_REASON_CONNECT_FAILED);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case APF_DISCONNECT: // (1) Intel AMT wants to completely disconnect. Not sure when this happens.
|
||||
{
|
||||
// First, we decode the message.
|
||||
struct LMEDisconnectMessage disconnectMessage;
|
||||
disconnectMessage.MessageType = APF_DISCONNECT;
|
||||
disconnectMessage.ReasonCode = ((APF_DISCONNECT_REASON_CODE)ntohl(((APF_DISCONNECT_MESSAGE *)rxBuffer)->ReasonCode));
|
||||
LMSDEBUG("LME requested to disconnect with reason code 0x%08x\r\n", disconnectMessage.ReasonCode);
|
||||
LME_Deinit(lmemodule);
|
||||
}
|
||||
break;
|
||||
case APF_SERVICE_REQUEST: // (5)
|
||||
{
|
||||
|
||||
int service = 0;
|
||||
APF_SERVICE_REQUEST_MESSAGE *pMessage = (APF_SERVICE_REQUEST_MESSAGE *)rxBuffer;
|
||||
pMessage->ServiceNameLength = ntohl(pMessage->ServiceNameLength);
|
||||
if (pMessage->ServiceNameLength == 18) {
|
||||
if (memcmp(pMessage->ServiceName, "pfwd@amt.intel.com", 18) == 0) service = 1;
|
||||
else if (memcmp(pMessage->ServiceName, "auth@amt.intel.com", 18) == 0) service = 2;
|
||||
}
|
||||
|
||||
if (service > 0)
|
||||
{
|
||||
if (service == 1)
|
||||
{
|
||||
LME_ServiceAccept(lmemodule, "pfwd@amt.intel.com");
|
||||
module->pfwdService = LME_STARTED;
|
||||
}
|
||||
else if (service == 2)
|
||||
{
|
||||
LME_ServiceAccept(lmemodule, "auth@amt.intel.com");
|
||||
}
|
||||
} else {
|
||||
LMSDEBUG("APF_SERVICE_REQUEST - APF_DISCONNECT_SERVICE_NOT_AVAILABLE\r\n");
|
||||
LME_Disconnect(lmemodule, APF_DISCONNECT_SERVICE_NOT_AVAILABLE);
|
||||
LME_Deinit(lmemodule);
|
||||
sem_post(&(module->Lock));
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case APF_CHANNEL_OPEN_CONFIRMATION: // (91) Intel AMT confirmation to an APF_CHANNEL_OPEN request.
|
||||
{
|
||||
|
||||
// First, we decode the message.
|
||||
struct LMEChannel* channel;
|
||||
APF_CHANNEL_OPEN_CONFIRMATION_MESSAGE *pMessage = (APF_CHANNEL_OPEN_CONFIRMATION_MESSAGE *)rxBuffer;
|
||||
|
||||
|
||||
struct LMEChannelOpenReplySuccessMessage channelOpenReply;
|
||||
channelOpenReply.RecipientChannel = ntohl(pMessage->RecipientChannel); // This is the identifier on our side.
|
||||
channelOpenReply.SenderChannel = ntohl(pMessage->SenderChannel); // This is the identifier on the Intel AMT side.
|
||||
channelOpenReply.InitialWindow = ntohl(pMessage->InitialWindowSize); // This is the starting window size for flow control.
|
||||
channel = &(module->Sessions[channelOpenReply.RecipientChannel]); // Get the current session for this message.
|
||||
|
||||
if (channel == NULL)
|
||||
break; // This should never happen.
|
||||
|
||||
LMSDEBUG("MEI OPEN OK OUR:%d AMT:%d\r\n", channelOpenReply.RecipientChannel, channelOpenReply.SenderChannel);
|
||||
|
||||
if (channel->status == LME_CS_PENDING_CONNECT) // If the channel is in PENDING_CONNECT mode, move the session to connected state.
|
||||
{
|
||||
channel->amtid = channelOpenReply.SenderChannel; // We have to set the Intel AMT identifier for this session.
|
||||
channel->txwindow = channelOpenReply.InitialWindow; // Set the session txwindow.
|
||||
channel->status = LME_CS_CONNECTED; // Now set the session as CONNECTED.
|
||||
LMSDEBUG("Channel %d now CONNECTED by AMT %d\r\n", channel->ourid, channel->socketmodule);
|
||||
if (channel->sockettype == 0) // If the current socket is PAUSED, lets resume it so data can start flowing again.
|
||||
{
|
||||
ILibAsyncSocket_Resume(channel->socketmodule); // TCP socket resume
|
||||
}
|
||||
}
|
||||
else if (channel->status == LME_CS_PENDING_LMS_DISCONNECT) // If the channel is in PENDING_DISCONNECT, we have to disconnect the session now. Happens when we disconnect while connection is pending. We don't want to stop a channel during connection, that is bad.
|
||||
{
|
||||
channel->amtid = channelOpenReply.SenderChannel; // We have to set the Intel AMT identifier for this session.
|
||||
LME_ChannelClose(&(module->MeConnection), channel->amtid, channel->ourid); // Send the Intel AMT close. We keep the channel in LME_CS_PENDING_LMS_DISCONNECT state until the close is confirmed.
|
||||
LMSDEBUG("Channel %d now CONNECTED by AMT %d, but CLOSING it now\r\n", channel->ourid, channel->socketmodule);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Here, we get an APF_CHANNEL_OPEN in an unexpected state, this should never happen.
|
||||
LMSDEBUG("Channel %d, unexpected CONNECTED by AMT %d\r\n", channel->ourid, channel->socketmodule);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case APF_CHANNEL_OPEN_FAILURE: // (92) Intel AMT rejected our connection attempt.
|
||||
{
|
||||
|
||||
// First, we decode the message.
|
||||
struct LMEChannel* channel;
|
||||
APF_CHANNEL_OPEN_FAILURE_MESSAGE *pMessage = (APF_CHANNEL_OPEN_FAILURE_MESSAGE *)rxBuffer;
|
||||
struct LMEChannelOpenReplyFailureMessage channelOpenReply;
|
||||
channelOpenReply.RecipientChannel = ntohl(pMessage->RecipientChannel); // This is the identifier on our side.
|
||||
|
||||
channelOpenReply.ReasonCode = (OPEN_FAILURE_REASON)(ntohl(pMessage->ReasonCode)); // Get the error reason code.
|
||||
channel = &(module->Sessions[channelOpenReply.RecipientChannel]); // Get the current session for this message.
|
||||
if (channel == NULL) break; // This should never happen.
|
||||
|
||||
LMSDEBUG("**OPEN FAIL OUR:%d ERR:%d\r\n", channelOpenReply.RecipientChannel, channelOpenReply.ReasonCode);
|
||||
|
||||
if (channel->errorcount++ >= 0 || channel->status == LME_CS_PENDING_LMS_DISCONNECT)
|
||||
{
|
||||
// Fail connection
|
||||
channel->status = LME_CS_FREE;
|
||||
LMSDEBUG("Channel %d now FREE by AMT\r\n", channel->ourid);
|
||||
sem_post(&(module->Lock));
|
||||
ILibAsyncSocket_Disconnect(channel->socketmodule);
|
||||
//ILibLMS_LaunchHoldingSessions(module);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Try again
|
||||
//ILibLMS_SetupConnection(module, channel->ourid);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case APF_CHANNEL_CLOSE: // (97) Intel AMT is closing this channel, we need to disconnect the LMS TCP connection
|
||||
{
|
||||
|
||||
// First, we decode the message.
|
||||
struct LMEChannel* channel;
|
||||
APF_CHANNEL_CLOSE_MESSAGE *pMessage = (APF_CHANNEL_CLOSE_MESSAGE *)rxBuffer;
|
||||
struct LMEChannelCloseMessage channelClose;
|
||||
channelClose.RecipientChannel = ntohl(pMessage->RecipientChannel); // This is the identifier on our side.
|
||||
channel = &(module->Sessions[channelClose.RecipientChannel]); // Get the current session for this message.
|
||||
if (channel == NULL) break; // This should never happen.
|
||||
|
||||
//LMSDEBUG("CLOSE OUR:%d\r\n", channelClose.RecipientChannel);
|
||||
|
||||
if (channel->status == LME_CS_CONNECTED)
|
||||
{
|
||||
if (ILibAsyncSocket_IsConnected(channel->socketmodule))
|
||||
{
|
||||
channel->status = LME_CS_PENDING_AMT_DISCONNECT;
|
||||
LMSDEBUG("Channel %d now PENDING_AMT_DISCONNECT by AMT, calling microstack disconnect %d\r\n", channel->ourid, channel->socketmodule);
|
||||
LME_ChannelClose(lmemodule, channel->amtid, channel->ourid);
|
||||
sem_post(&(module->Lock));
|
||||
if (channel->sockettype == 0) // If the current socket is PAUSED, lets resume it so data can start flowing again.
|
||||
{
|
||||
ILibAsyncSocket_Disconnect(channel->socketmodule); // TCP socket close
|
||||
}
|
||||
|
||||
sem_wait(&(module->Lock));
|
||||
channel->status = LME_CS_FREE;
|
||||
disconnects++;
|
||||
LMSDEBUG("Channel %d now FREE by AMT\r\n", channel->ourid);
|
||||
}
|
||||
else
|
||||
{
|
||||
channel->status = LME_CS_FREE;
|
||||
disconnects++;
|
||||
LMSDEBUG("Channel %d now FREE by AMT\r\n", channel->ourid);
|
||||
}
|
||||
}
|
||||
else if (channel->status == LME_CS_PENDING_LMS_DISCONNECT)
|
||||
{
|
||||
channel->status = LME_CS_FREE;
|
||||
disconnects++;
|
||||
LMSDEBUG("Channel %d now FREE by AMT\r\n", channel->ourid);
|
||||
}
|
||||
else
|
||||
{
|
||||
LMSDEBUG("Channel %d CLOSE, UNEXPECTED STATE %d\r\n", channel->ourid, channel->status);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case APF_CHANNEL_DATA: // (94) Intel AMT is sending data that we must relay into an LMS TCP connection.
|
||||
{
|
||||
//sem_wait(&(module->Lock));
|
||||
|
||||
struct LMEChannel* channel;
|
||||
APF_CHANNEL_DATA_MESSAGE *pMessage = (APF_CHANNEL_DATA_MESSAGE *)rxBuffer;
|
||||
struct LMEChannelDataMessage channelData;
|
||||
enum ILibAsyncSocket_SendStatus r;
|
||||
channelData.MessageType = APF_CHANNEL_DATA;
|
||||
channelData.RecipientChannel = ntohl(pMessage->RecipientChannel);
|
||||
channelData.DataLength = ntohl(pMessage->DataLength);
|
||||
channelData.Data = (unsigned char*)rxBuffer + sizeof(APF_CHANNEL_DATA_MESSAGE);
|
||||
channel = &(module->Sessions[channelData.RecipientChannel]);
|
||||
|
||||
|
||||
if (channel == NULL || channel->socketmodule == NULL){
|
||||
sem_post(&(module->Lock));
|
||||
break;
|
||||
}
|
||||
|
||||
if (channel->sockettype == 0)
|
||||
{
|
||||
r = ILibAsyncSocket_Send(channel->socketmodule, (char*)(channelData.Data), channelData.DataLength, ILibAsyncSocket_MemoryOwnership_USER); // TCP socket
|
||||
}
|
||||
|
||||
channel->rxwindow += channelData.DataLength;
|
||||
if (r == ILibAsyncSocket_ALL_DATA_SENT && channel->rxwindow > 1024) {
|
||||
LME_ChannelWindowAdjust(lmemodule, channel->amtid, channel->rxwindow); channel->rxwindow = 0;
|
||||
}
|
||||
//sem_post(&(module->Lock));
|
||||
}
|
||||
break;
|
||||
case APF_CHANNEL_WINDOW_ADJUST: // 93
|
||||
{
|
||||
//sem_wait(&(module->Lock));
|
||||
|
||||
struct LMEChannel* channel;
|
||||
APF_WINDOW_ADJUST_MESSAGE *pMessage = (APF_WINDOW_ADJUST_MESSAGE *)rxBuffer;
|
||||
struct LMEChannelWindowAdjustMessage channelWindowAdjust;
|
||||
channelWindowAdjust.MessageType = APF_CHANNEL_WINDOW_ADJUST;
|
||||
channelWindowAdjust.RecipientChannel = ntohl(pMessage->RecipientChannel);
|
||||
channelWindowAdjust.BytesToAdd = ntohl(pMessage->BytesToAdd);
|
||||
channel = &(module->Sessions[channelWindowAdjust.RecipientChannel]);
|
||||
if (channel == NULL || channel->status == LME_CS_FREE){
|
||||
sem_post(&(module->Lock));
|
||||
break;
|
||||
}
|
||||
channel->txwindow += channelWindowAdjust.BytesToAdd;
|
||||
if (channel->sockettype == 0)
|
||||
{
|
||||
ILibAsyncSocket_Resume(channel->socketmodule); // TCP socket
|
||||
}
|
||||
//sem_post(&(module->Lock));
|
||||
}
|
||||
break;
|
||||
case APF_PROTOCOLVERSION: // 192
|
||||
{
|
||||
APF_PROTOCOL_VERSION_MESSAGE *pMessage = (APF_PROTOCOL_VERSION_MESSAGE *)rxBuffer;
|
||||
struct LMEProtocolVersionMessage protVersion;
|
||||
protVersion.MajorVersion = ntohl(pMessage->MajorVersion);
|
||||
protVersion.MinorVersion = ntohl(pMessage->MinorVersion);
|
||||
protVersion.TriggerReason = (APF_TRIGGER_REASON)ntohl(pMessage->TriggerReason);
|
||||
|
||||
switch (module->handshakingStatus)
|
||||
{
|
||||
case LME_AGREED:
|
||||
case LME_NOT_INITIATED:
|
||||
{
|
||||
LME_ProtocolVersion(lmemodule, 1, 0, protVersion.TriggerReason);
|
||||
}
|
||||
case LME_INITIATED:
|
||||
if (protVersion.MajorVersion != 1 || protVersion.MinorVersion != 0)
|
||||
{
|
||||
LMSDEBUG("LME Version %d.%d is not supported.\r\n", protVersion.MajorVersion, protVersion.MinorVersion);
|
||||
LME_Disconnect(lmemodule, APF_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED);
|
||||
LME_Deinit(lmemodule);
|
||||
sem_post(&(module->Lock));
|
||||
return;
|
||||
}
|
||||
module->AmtProtVersionMajor = protVersion.MajorVersion;
|
||||
module->AmtProtVersionMinor = protVersion.MinorVersion;
|
||||
module->handshakingStatus = LME_AGREED;
|
||||
break;
|
||||
default:
|
||||
LME_Disconnect(lmemodule, APF_DISCONNECT_BY_APPLICATION);
|
||||
LME_Deinit(lmemodule);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case APF_USERAUTH_REQUEST: // 50
|
||||
{
|
||||
// _lme.UserAuthSuccess();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Unknown request.
|
||||
LMSDEBUG("**Unknown LME command: %d\r\n", ((unsigned char*)rxBuffer)[0]);
|
||||
LME_Disconnect(lmemodule, APF_DISCONNECT_PROTOCOL_ERROR);
|
||||
LME_Deinit(lmemodule);
|
||||
break;
|
||||
}
|
||||
|
||||
sem_post(&(module->Lock));
|
||||
//if (disconnects > 0) ILibLMS_LaunchHoldingSessions(module); // If disconnects is set to anything, we have free session slots we can fill up.
|
||||
}
|
||||
|
||||
void ILibLMS_OnReceive(ILibAsyncServerSocket_ServerModule AsyncServerSocketModule, ILibAsyncServerSocket_ConnectionToken ConnectionToken, char* buffer, int *p_beginPointer, int endPointer, ILibAsyncServerSocket_OnInterrupt *OnInterrupt, void **user, int *PAUSE)
|
||||
{
|
||||
int r, maxread = endPointer;
|
||||
struct ILibLMS_StateModule* module = (struct ILibLMS_StateModule*)ILibAsyncServerSocket_GetTag(AsyncServerSocketModule);
|
||||
struct LMEChannel* channel = (struct LMEChannel*)*user;
|
||||
|
||||
UNREFERENCED_PARAMETER( AsyncServerSocketModule );
|
||||
UNREFERENCED_PARAMETER( ConnectionToken );
|
||||
UNREFERENCED_PARAMETER( OnInterrupt );
|
||||
UNREFERENCED_PARAMETER( PAUSE );
|
||||
|
||||
if (channel == NULL) return;
|
||||
sem_wait(&(module->Lock));
|
||||
if (channel->socketmodule != ConnectionToken) { sem_post(&(module->Lock)); ILibAsyncSocket_Disconnect(ConnectionToken); return; }
|
||||
if (channel->txwindow < endPointer) maxread = channel->txwindow;
|
||||
if (channel->status != LME_CS_CONNECTED || maxread == 0) { *PAUSE = 1; sem_post(&(module->Lock)); return; }
|
||||
//printf("%.*s", maxread, buffer);
|
||||
r = LME_ChannelData(&(module->MeConnection), channel->amtid, maxread, (unsigned char*)buffer);
|
||||
//LMSDEBUG("ILibLMS_OnReceive, status = %d, txwindow = %d, endPointer = %d, r = %d\r\n", channel->status, channel->txwindow, endPointer, r);
|
||||
if (r != maxread)
|
||||
{
|
||||
//LMSDEBUG("ILibLMS_OnReceive, DISCONNECT %d\r\n", channel->ourid);
|
||||
sem_post(&(module->Lock));
|
||||
ILibAsyncSocket_Disconnect(ConnectionToken); // Drop the connection
|
||||
return;
|
||||
}
|
||||
channel->txwindow -= maxread;
|
||||
*p_beginPointer = maxread;
|
||||
sem_post(&(module->Lock));
|
||||
}
|
||||
|
||||
void ILibLMS_SetupConnection(struct ILibLMS_StateModule* module, int i)
|
||||
{
|
||||
int rport = 0;
|
||||
char* laddr = NULL;
|
||||
struct sockaddr_in6 remoteAddress;
|
||||
|
||||
if (module->Sessions[i].sockettype == 0)
|
||||
{
|
||||
// Fetch the socket remote TCP address
|
||||
ILibAsyncSocket_GetRemoteInterface(module->Sessions[i].socketmodule, (struct sockaddr*)&remoteAddress);
|
||||
if (remoteAddress.sin6_family == AF_INET6)
|
||||
{
|
||||
laddr = "::1"; // TODO: decode this properly into a string
|
||||
rport = ntohs(remoteAddress.sin6_port);
|
||||
}
|
||||
else
|
||||
{
|
||||
laddr = "127.0.0.1"; // TODO: decode this properly into a string
|
||||
rport = ntohs(((struct sockaddr_in*)(&remoteAddress))->sin_port);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fetch the socket remote web socket address
|
||||
laddr = "127.0.0.1"; // TODO: decode this properly into a string
|
||||
rport = 123; // TODO: decode the remote port
|
||||
}
|
||||
|
||||
// Setup a new LME session
|
||||
LME_ChannelOpenForwardedRequest(&(module->MeConnection), (unsigned int)i, laddr, module->Sessions[i].localport, laddr, rport);
|
||||
//LMSDEBUG("ILibLMS_OnReceive, CONNECT %d\r\n", i);
|
||||
}
|
||||
|
||||
|
||||
int OnConnect = 0;
|
||||
void ILibLMS_OnConnect(ILibAsyncServerSocket_ServerModule AsyncServerSocketModule, ILibAsyncServerSocket_ConnectionToken ConnectionToken, void **user)
|
||||
{
|
||||
OnConnect++;
|
||||
LMSDEBUG("OnCOnnect:%d", OnConnect);
|
||||
int i, sessionid = -1, activecount = 0;
|
||||
struct ILibLMS_StateModule* module = (struct ILibLMS_StateModule*)ILibAsyncServerSocket_GetTag(AsyncServerSocketModule);
|
||||
|
||||
sem_wait(&(module->Lock));
|
||||
|
||||
// Count the number of active sessions
|
||||
activecount = LMS_MAX_SESSIONS;
|
||||
for (i = 0; i < LMS_MAX_SESSIONS; i++) {
|
||||
if (module->Sessions[i].status == LME_CS_FREE || module->Sessions[i].status == LME_CS_CONNECTION_WAIT) {
|
||||
activecount--;
|
||||
}
|
||||
}
|
||||
|
||||
sessionid=GetFreeSlot(module);
|
||||
|
||||
// Look for an empty session
|
||||
//for (i = 1; i < LMS_MAX_SESSIONS; i++) {
|
||||
// if (module->Sessions[i].status == LME_CS_FREE) {
|
||||
// sessionid = i;
|
||||
// break;
|
||||
// }
|
||||
//}
|
||||
if (sessionid == -1)
|
||||
{
|
||||
sem_post(&(module->Lock));
|
||||
LMSDEBUG("ILibLMS_OnConnect NO SESSION SLOTS AVAILABLE\r\n");
|
||||
ILibAsyncSocket_Disconnect(ConnectionToken); // Drop the connection
|
||||
return;
|
||||
}
|
||||
i = sessionid;
|
||||
|
||||
// LMSDEBUG("USING SLOT OUR:%d\r\n", i);
|
||||
module->Sessions[i].amtid = -1;
|
||||
module->Sessions[i].ourid = i;
|
||||
module->Sessions[i].sockettype = 0; // TCP Type
|
||||
module->Sessions[i].socketmodule = ConnectionToken;
|
||||
module->Sessions[i].rxwindow = 0;
|
||||
module->Sessions[i].txwindow = 0;
|
||||
module->Sessions[i].localport = ILibAsyncServerSocket_GetPortNumber(AsyncServerSocketModule);
|
||||
module->Sessions[i].errorcount = 0;
|
||||
*user = &(module->Sessions[i]);
|
||||
|
||||
/*
|
||||
if (activecount >= LMS_MAX_CONNECTIONS)
|
||||
{
|
||||
module->Sessions[i].status = LME_CS_CONNECTION_WAIT;
|
||||
LMSDEBUG("ILibLMS_OnConnect %d (HOLDING)\r\n", i);
|
||||
}
|
||||
else
|
||||
*/
|
||||
{
|
||||
module->Sessions[i].status = LME_CS_PENDING_CONNECT;
|
||||
LMSDEBUG("ILibLMS_OnConnect %d\r\n", i);
|
||||
ILibLMS_SetupConnection(module, i);
|
||||
}
|
||||
|
||||
sem_post(&(module->Lock));
|
||||
}
|
||||
|
||||
void ILibLMS_OnDisconnect(ILibAsyncServerSocket_ServerModule AsyncServerSocketModule, ILibAsyncServerSocket_ConnectionToken ConnectionToken, void *user)
|
||||
{
|
||||
int disconnects = 0;
|
||||
struct ILibLMS_StateModule* module = (struct ILibLMS_StateModule*)ILibAsyncServerSocket_GetTag(AsyncServerSocketModule);
|
||||
struct LMEChannel* channel = (struct LMEChannel*)user;
|
||||
UNREFERENCED_PARAMETER( ConnectionToken );
|
||||
|
||||
sem_wait(&(module->Lock));
|
||||
|
||||
if (channel == NULL || channel->socketmodule != ConnectionToken)
|
||||
{
|
||||
LMSDEBUG("****ILibLMS_OnDisconnect EXIT\r\n");
|
||||
sem_post(&(module->Lock));
|
||||
return;
|
||||
}
|
||||
|
||||
LMSDEBUG("ILibLMS_OnDisconnect, Channel %d, %d\r\n", channel->ourid, ConnectionToken);
|
||||
|
||||
if (channel->status == LME_CS_CONNECTED)
|
||||
{
|
||||
channel->status = LME_CS_PENDING_LMS_DISCONNECT;
|
||||
if (channel->amtid!=-1 && !LME_ChannelClose(&(module->MeConnection), channel->amtid, channel->ourid))
|
||||
{
|
||||
channel->status = LME_CS_FREE;
|
||||
disconnects++;
|
||||
LMSDEBUG("Channel %d now FREE by LMS because of failed close\r\n", channel->ourid);
|
||||
}
|
||||
else
|
||||
{
|
||||
LMSDEBUG("Channel %d now PENDING_LMS_DISCONNECT by LMS\r\n", channel->ourid);
|
||||
//LMSDEBUG("LME_ChannelClose OK\r\n");
|
||||
}
|
||||
}
|
||||
else if (channel->status == LME_CS_PENDING_CONNECT)
|
||||
{
|
||||
channel->status = LME_CS_PENDING_LMS_DISCONNECT;
|
||||
LMSDEBUG("Channel %d now PENDING_DISCONNECT by LMS\r\n", channel->ourid);
|
||||
}
|
||||
else if (channel->status == LME_CS_CONNECTION_WAIT)
|
||||
{
|
||||
channel->status = LME_CS_FREE;
|
||||
disconnects++;
|
||||
LMSDEBUG("Channel %d now FREE by LMS\r\n", channel->ourid);
|
||||
}
|
||||
//LMSDEBUG("ILibLMS_OnDisconnect, DISCONNECT %d, status = %d\r\n", channel->ourid, channel->status);
|
||||
sem_post(&(module->Lock));
|
||||
|
||||
//if (disconnects > 0) ILibLMS_LaunchHoldingSessions(module);
|
||||
}
|
||||
|
||||
void ILibLMS_OnSendOK(ILibAsyncServerSocket_ServerModule AsyncServerSocketModule, ILibAsyncServerSocket_ConnectionToken ConnectionToken, void *user)
|
||||
{
|
||||
struct ILibLMS_StateModule* module = (struct ILibLMS_StateModule*)ILibAsyncServerSocket_GetTag(AsyncServerSocketModule);
|
||||
struct LMEChannel* channel = (struct LMEChannel*)user;
|
||||
UNREFERENCED_PARAMETER( ConnectionToken );
|
||||
|
||||
// Ok to send more on this socket, adjust the window
|
||||
sem_wait(&(module->Lock));
|
||||
if (channel->rxwindow != 0)
|
||||
{
|
||||
//LMSDEBUG("LME_ChannelWindowAdjust id=%d, rxwindow=%d\r\n", channel->amtid, channel->rxwindow);
|
||||
LME_ChannelWindowAdjust(&(module->MeConnection), channel->amtid, channel->rxwindow);
|
||||
channel->rxwindow = 0;
|
||||
}
|
||||
sem_post(&(module->Lock));
|
||||
}
|
||||
// Private method called when the chain is destroyed, we want to do our cleanup here
|
||||
void ILibLMS_Destroy(void *object)
|
||||
{
|
||||
struct ILibLMS_StateModule* module = (struct ILibLMS_StateModule*)object;
|
||||
UNREFERENCED_PARAMETER( object );
|
||||
|
||||
sem_wait(&(module->Lock));
|
||||
LME_Disconnect(&(module->MeConnection), APF_DISCONNECT_BY_APPLICATION);
|
||||
LME_Exit(&(module->MeConnection));
|
||||
sem_destroy(&(module->Lock));
|
||||
if (IlibExternLMS == module) { IlibExternLMS = NULL; } // Clear the global reference to the the LMS module.
|
||||
}
|
||||
|
||||
// Create a new Reflector module.
|
||||
struct ILibLMS_StateModule *ILibLMS_Create(void *Chain)
|
||||
{
|
||||
struct ILibLMS_StateModule *module;
|
||||
|
||||
// Allocate the new module
|
||||
module = (struct ILibLMS_StateModule*)malloc(sizeof(struct ILibLMS_StateModule));
|
||||
if (module == NULL) { ILIBCRITICALEXIT(254); }
|
||||
memset(module, 0, sizeof(struct ILibLMS_StateModule));
|
||||
|
||||
// Setup MEI with LMS interface, if we can't return null
|
||||
if (LME_Init(&(module->MeConnection), &ILibLMS_MEICallback, module) == 0) {
|
||||
free(module);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Setup the module
|
||||
module->ChainLink.DestroyHandler = &ILibLMS_Destroy;
|
||||
module->ChainLink.ParentChain = Chain;
|
||||
sem_init(&(module->Lock), 0, 1);
|
||||
|
||||
// TCP servers
|
||||
module->Server1 = ILibCreateAsyncServerSocketModule(Chain, LMS_MAX_CONNECTIONS, 16992, 4096, 0, &ILibLMS_OnConnect, &ILibLMS_OnDisconnect, &ILibLMS_OnReceive, NULL, &ILibLMS_OnSendOK);
|
||||
if (module->Server1 == NULL) { sem_destroy(&(module->Lock)); free(module); return NULL; }
|
||||
ILibAsyncServerSocket_SetTag(module->Server1, module);
|
||||
|
||||
module->Server2 = ILibCreateAsyncServerSocketModule(Chain, LMS_MAX_CONNECTIONS, 16993, 4096, 0, &ILibLMS_OnConnect, &ILibLMS_OnDisconnect, &ILibLMS_OnReceive, NULL, &ILibLMS_OnSendOK);
|
||||
if (module->Server2 == NULL) { sem_destroy(&(module->Lock)); free(module->Server1); free(module); return NULL; }
|
||||
ILibAsyncServerSocket_SetTag(module->Server2, module);
|
||||
|
||||
|
||||
|
||||
|
||||
// TODO: US6986 - The meshcommander site should not be served on localhost:16994.
|
||||
// This code should be commented out - in the future(late 2018) IMC could be put there instead.
|
||||
// Web Server
|
||||
//module->WebServer = ILibWebServer_CreateEx(Chain, 8, 16994, 2, &ILibLMS_WebServer_OnSession, module);
|
||||
|
||||
IlibExternLMS = module; // Set the global reference to the LMS module.
|
||||
ILibAddToChain(Chain, module); // Add this module to the chain.
|
||||
return module;
|
||||
}
|
||||
|
||||
#endif
|
26
MicroLMS/microstack/ILibLMS.h
Normal file
26
MicroLMS/microstack/ILibLMS.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#if !defined(_NOHECI)
|
||||
|
||||
#ifndef __ILibLMS__
|
||||
#define __ILibLMS__
|
||||
#include "ILibAsyncServerSocket.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct ILibLMS_StateModule *ILibLMS_Create(void *Chain);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
8763
MicroLMS/microstack/ILibParsers.c
Normal file
8763
MicroLMS/microstack/ILibParsers.c
Normal file
File diff suppressed because it is too large
Load Diff
1302
MicroLMS/microstack/ILibParsers.h
Normal file
1302
MicroLMS/microstack/ILibParsers.h
Normal file
File diff suppressed because it is too large
Load Diff
95
MicroLMS/microstack/ILibRemoteLogging.h
Normal file
95
MicroLMS/microstack/ILibRemoteLogging.h
Normal file
@@ -0,0 +1,95 @@
|
||||
/* 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 __ILIBREMOTELOGGING__
|
||||
#define __ILIBREMOTELOGGING__
|
||||
|
||||
#include "ILibParsers.h"
|
||||
|
||||
/*! \defgroup ILibRemoteLogging ILibRemoteLogging Module
|
||||
@{
|
||||
*/
|
||||
//! Module Types
|
||||
typedef enum ILibRemoteLogging_Modules
|
||||
{
|
||||
ILibRemoteLogging_Modules_UNKNOWN = 0x00, //!< UNKNOWN Module
|
||||
ILibRemoteLogging_Modules_Logger = 0x01, //!< RESERVED: Logger
|
||||
ILibRemoteLogging_Modules_WebRTC_STUN_ICE = 0x02, //!< WebRTC: STUN/ICE
|
||||
ILibRemoteLogging_Modules_WebRTC_DTLS = 0x04, //!< WebRTC: DTLS
|
||||
ILibRemoteLogging_Modules_WebRTC_SCTP = 0x08, //!< WebRTC: SCTP
|
||||
ILibRemoteLogging_Modules_Agent_GuardPost = 0x10, //!< Mesh Agent: Guard Post
|
||||
ILibRemoteLogging_Modules_Agent_P2P = 0x20, //!< Mesh Agent: Peer to Peer
|
||||
ILibRemoteLogging_Modules_Agent_KVM = 0x200, //!< Mesh AGent: KVM
|
||||
ILibRemoteLogging_Modules_Microstack_AsyncSocket = 0x40, //!< Microstack: AsyncSocket, AsyncServerSocket, AsyncUDPSocket
|
||||
ILibRemoteLogging_Modules_Microstack_Web = 0x80, //!< Microstack: WebServer, WebSocket, WebClient
|
||||
ILibRemoteLogging_Modules_Microstack_Pipe = 0x400,//!< Microstack: Pipe
|
||||
ILibRemoteLogging_Modules_Microstack_Generic = 0x100,//!< Microstack: Generic
|
||||
ILibRemoteLogging_Modules_ConsolePrint = 0x4000
|
||||
}ILibRemoteLogging_Modules;
|
||||
//! Logging Flags
|
||||
typedef enum ILibRemoteLogging_Flags
|
||||
{
|
||||
ILibRemoteLogging_Flags_NONE = 0x00, //!< NONE
|
||||
ILibRemoteLogging_Flags_DisableLogging = 0x01, //!< DISABLED
|
||||
ILibRemoteLogging_Flags_VerbosityLevel_1 = 0x02, //!< Verbosity Level 1
|
||||
ILibRemoteLogging_Flags_VerbosityLevel_2 = 0x04, //!< Verbosity Level 2
|
||||
ILibRemoteLogging_Flags_VerbosityLevel_3 = 0x08, //!< Verbosity Level 3
|
||||
ILibRemoteLogging_Flags_VerbosityLevel_4 = 0x10, //!< Verbosity Level 4
|
||||
ILibRemoteLogging_Flags_VerbosityLevel_5 = 0x20, //!< Verbosity Level 5
|
||||
}ILibRemoteLogging_Flags;
|
||||
|
||||
typedef enum ILibRemoteLogging_Command_Logger_Flags
|
||||
{
|
||||
ILibRemoteLogging_Command_Logger_Flags_ENABLE = 0x100, //!< Enables/Disables File Logging
|
||||
ILibRemoteLogging_Command_Logger_Flags_RESET_FILE = 0x200, //!< Erases the log file
|
||||
ILibRemoteLogging_Command_Logger_Flags_READ_FILE = 0x400, //!< Reads the log file
|
||||
ILibRemoteLogging_Command_Logger_Flags_RESET_FLAGS = 0x800, //!< Sets the Module/Flags to log to file
|
||||
}ILibRemoteLogging_Command_Logger_Flags;
|
||||
|
||||
#define ILibTransports_RemoteLogging_FileTransport 0x70
|
||||
typedef void* ILibRemoteLogging;
|
||||
typedef void (*ILibRemoteLogging_OnWrite)(ILibRemoteLogging module, char* data, int dataLen, void *userContext);
|
||||
typedef void (*ILibRemoteLogging_OnCommand)(ILibRemoteLogging sender, ILibRemoteLogging_Modules module, unsigned short flags, char* data, int dataLen, void *userContext);
|
||||
typedef void(*ILibRemoteLogging_OnRawForward)(ILibRemoteLogging sender, ILibRemoteLogging_Modules module, ILibRemoteLogging_Flags flags, char *buffer, int bufferLen);
|
||||
|
||||
#ifdef _REMOTELOGGING
|
||||
char* ILibRemoteLogging_ConvertAddress(struct sockaddr* addr);
|
||||
char* ILibRemoteLogging_ConvertToHex(char* inVal, int inValLength);
|
||||
void ILibRemoteLogging_printf(ILibRemoteLogging loggingModule, ILibRemoteLogging_Modules module, ILibRemoteLogging_Flags flags, char* format, ...);
|
||||
|
||||
ILibRemoteLogging ILibRemoteLogging_Create(ILibRemoteLogging_OnWrite onOutput);
|
||||
ILibTransport* ILibRemoteLogging_CreateFileTransport(ILibRemoteLogging loggingModule, ILibRemoteLogging_Modules modules, ILibRemoteLogging_Flags flags, char* path, int pathLen);
|
||||
void ILibRemoteLogging_Destroy(ILibRemoteLogging logger);
|
||||
void ILibRemoteLogging_SetRawForward(ILibRemoteLogging logger, int bufferOffset, ILibRemoteLogging_OnRawForward onRawForward);
|
||||
|
||||
void ILibRemoteLogging_DeleteUserContext(ILibRemoteLogging logger, void *userContext);
|
||||
void ILibRemoteLogging_RegisterCommandSink(ILibRemoteLogging logger, ILibRemoteLogging_Modules module, ILibRemoteLogging_OnCommand sink);
|
||||
int ILibRemoteLogging_Dispatch(ILibRemoteLogging loggingModule, char* data, int dataLen, void *userContext);
|
||||
#define ILibRemoteLogging_ReadModuleType(data) ((ILibRemoteLogging_Modules)ntohs(((unsigned short*)data)[0]))
|
||||
#define ILibRemoteLogging_ReadFlags(data) ((ILibRemoteLogging_Flags)ntohs(((unsigned short*)data)[1]))
|
||||
int ILibRemoteLogging_IsModuleSet(ILibRemoteLogging loggingModule, ILibRemoteLogging_Modules module);
|
||||
void ILibRemoteLogging_Forward(ILibRemoteLogging loggingModule, char* data, int dataLen);
|
||||
#else
|
||||
#define ILibRemoteLogging_ConvertAddress(...) ;
|
||||
#define ILibRemoteLogging_ConvertToHex(...) ;
|
||||
#define ILibRemoteLogging_printf(...) ;
|
||||
#define ILibRemoteLogging_Create(...) NULL;
|
||||
#define ILibRemoteLogging_SetRawForward(...) ;
|
||||
#define ILibRemoteLogging_CreateFileTransport(...) NULL;
|
||||
#define ILibRemoteLogging_Destroy(...) ;
|
||||
#define ILibRemoteLogging_DeleteUserContext(...) ;
|
||||
#define ILibRemoteLogging_RegisterCommandSink(...) ;
|
||||
#define ILibRemoteLogging_Dispatch(...) ;
|
||||
#define ILibRemoteLogging_ReadModuleType(data) ILibRemoteLogging_Modules_UNKNOWN
|
||||
#define ILibRemoteLogging_ReadFlags(data) ILibRemoteLogging_Flags_NONE
|
||||
#define ILibRemoteLogging_IsModuleSet(...) 0
|
||||
#define ILibRemoteLogging_Forward(...) ;
|
||||
#endif
|
||||
|
||||
/*! @} */
|
||||
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user