mirror of
https://github.com/Ylianst/MeshAgent
synced 2026-01-09 12:03:41 +00:00
First commit of MeshAgent for MeshCentral
This commit is contained in:
723
microstack/ILibAsyncServerSocket.c
Normal file
723
microstack/ILibAsyncServerSocket.c
Normal file
@@ -0,0 +1,723 @@
|
||||
/*
|
||||
Copyright 2006 - 2017 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(_MINCORE)
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include <crtdbg.h>
|
||||
#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;
|
||||
#ifndef MICROSTACK_NOTLS
|
||||
ILibAsyncServerSocket_OnSSL OnSSLContext;
|
||||
SSL_CTX *ssl_ctx;
|
||||
#ifdef MICROSTACK_TLS_DETECT
|
||||
int TLSDetectEnabled;
|
||||
#endif
|
||||
#endif
|
||||
}ILibAsyncServerSocketModule;
|
||||
struct ILibAsyncServerSocket_Data
|
||||
{
|
||||
struct ILibAsyncServerSocketModule *module;
|
||||
ILibAsyncServerSocket_BufferReAllocated Callback;
|
||||
void *user;
|
||||
};
|
||||
|
||||
const int ILibMemory_ASYNCSERVERSOCKET_CONTAINERSIZE = (const int)sizeof(ILibAsyncServerSocketModule);
|
||||
|
||||
// Prototypes
|
||||
void ILibAsyncServerSocket_OnData(ILibAsyncSocket_SocketModule socketModule, char* buffer, int *p_beginPointer, int endPointer, void(**OnInterrupt)(void *AsyncSocketMoudle, void *user), void **user, int *PAUSE);
|
||||
void ILibAsyncServerSocket_OnConnectSink(ILibAsyncSocket_SocketModule socketModule, int Connected, void *user);
|
||||
void ILibAsyncServerSocket_OnDisconnectSink(ILibAsyncSocket_SocketModule socketModule, void *user);
|
||||
void ILibAsyncServerSocket_OnSendOKSink(ILibAsyncSocket_SocketModule socketModule, void *user);
|
||||
|
||||
|
||||
/*! \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_WCE
|
||||
flags = 1;
|
||||
ioctlsocket(module->ListenSocket, FIONBIO, &flags);
|
||||
#elif WIN32
|
||||
flags = 1;
|
||||
ioctlsocket(module->ListenSocket, FIONBIO, (u_long *)(&flags));
|
||||
#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;
|
||||
//struct sockaddr_in6 receivingAddress;
|
||||
|
||||
#ifdef _POSIX
|
||||
socklen_t addrlen;
|
||||
//socklen_t receivingAddressLength = sizeof(struct sockaddr_in6);
|
||||
#else
|
||||
int addrlen;
|
||||
//int receivingAddressLength = sizeof(struct sockaddr_in6);
|
||||
#endif
|
||||
|
||||
struct ILibAsyncServerSocketModule *module = (struct ILibAsyncServerSocketModule*)socketModule;
|
||||
int i,flags;
|
||||
#ifdef _WIN32_WCE
|
||||
SOCKET NewSocket;
|
||||
#elif 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
|
||||
//printf("Accept NewSocket=%d\r\n", NewSocket);
|
||||
|
||||
// This code rejects connections that are from out-of-scope addresses (Outside the subnet, outside local host...)
|
||||
// It needs to be updated to IPv6.
|
||||
/*
|
||||
if (NewSocket != ~0)
|
||||
{
|
||||
switch(module->scope)
|
||||
{
|
||||
case ILibServerScope_LocalLoopback:
|
||||
// Check that the caller ip address is the same as the receive IP address
|
||||
getsockname(NewSocket, (struct sockaddr*)&receivingAddress, &receivingAddressLength);
|
||||
if (((struct sockaddr_in*)&receivingAddress)->sin_addr.s_addr != ((struct sockaddr_in*)&addr)->sin_addr.s_addr) // TODO: NOT IPv6 COMPILANT!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
{
|
||||
#if defined(WIN32) || defined(_WIN32_WCE)
|
||||
closesocket(NewSocket);
|
||||
#else
|
||||
close(NewSocket);
|
||||
#endif
|
||||
NewSocket = ~0;
|
||||
}
|
||||
break;
|
||||
case ILibServerScope_LocalSegment:
|
||||
getsockname(NewSocket, (struct sockaddr*)&receivingAddress, &receivingAddressLength);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
*/
|
||||
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_WCE
|
||||
flags = 1;
|
||||
ioctlsocket(NewSocket ,FIONBIO, &flags);
|
||||
#elif WIN32
|
||||
flags = 1;
|
||||
ioctlsocket(NewSocket, FIONBIO, (u_long *)(&flags));
|
||||
#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_UpdateCallbacks(module->AsyncSockets[i], ILibAsyncServerSocket_OnData, ILibAsyncServerSocket_OnConnectSink, ILibAsyncServerSocket_OnDisconnectSink, ILibAsyncServerSocket_OnSendOKSink);
|
||||
ILibAsyncSocket_SetRemoteAddress(module->AsyncSockets[i], (struct sockaddr*)&addr);
|
||||
|
||||
#ifndef MICROSTACK_NOTLS
|
||||
if (module->ssl_ctx != NULL)
|
||||
{
|
||||
// Accept a new TLS connection
|
||||
#ifdef MICROSTACK_TLS_DETECT
|
||||
SSL* ctx = ILibAsyncSocket_SetSSLContext(module->AsyncSockets[i], module->ssl_ctx, module->TLSDetectEnabled == 0 ? ILibAsyncSocket_TLS_Mode_Server : ILibAsyncSocket_TLS_Mode_Server_with_TLSDetectLogic);
|
||||
#else
|
||||
SSL* ctx = ILibAsyncSocket_SetSSLContext(module->AsyncSockets[i], module->ssl_ctx, ILibAsyncSocket_TLS_Mode_Server);
|
||||
#endif
|
||||
if (ctx != NULL && module->OnSSLContext != NULL) { module->OnSSLContext(module, module->AsyncSockets[i], ctx, &(data->user)); }
|
||||
}
|
||||
else
|
||||
#endif
|
||||
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);
|
||||
module->AsyncSockets = NULL;
|
||||
if (module->ListenSocket != (SOCKET)~0)
|
||||
{
|
||||
#ifdef _WIN32_WCE
|
||||
closesocket(module->ListenSocket);
|
||||
#elif 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) { free(data); data = NULL; return; } // Connection Failed, clean up
|
||||
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); data = NULL; }
|
||||
}
|
||||
//
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef MICROSTACK_NOTLS
|
||||
void* ILibAsyncServerSocket_GetSSL_CTX(ILibAsyncServerSocket_ServerModule ILibAsyncSocketModule)
|
||||
{
|
||||
return(((struct ILibAsyncServerSocketModule*)ILibAsyncSocketModule)->ssl_ctx);
|
||||
}
|
||||
#ifdef MICROSTACK_TLS_DETECT
|
||||
void ILibAsyncServerSocket_SetSSL_CTX(ILibAsyncServerSocket_ServerModule ILibAsyncSocketModule, void *ssl_ctx, int enableTLSDetect)
|
||||
#else
|
||||
void ILibAsyncServerSocket_SetSSL_CTX(ILibAsyncServerSocket_ServerModule ILibAsyncSocketModule, void *ssl_ctx)
|
||||
#endif
|
||||
{
|
||||
if (ILibAsyncSocketModule != NULL && ssl_ctx != NULL)
|
||||
{
|
||||
struct ILibAsyncServerSocketModule *module = (struct ILibAsyncServerSocketModule*)ILibAsyncSocketModule;
|
||||
module->ssl_ctx = (SSL_CTX *)ssl_ctx;
|
||||
#ifdef MICROSTACK_TLS_DETECT
|
||||
module->TLSDetectEnabled = enableTLSDetect;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void ILibAsyncServerSocket_RemoveFromChainSink(void *chain, void *user)
|
||||
{
|
||||
ILibAsyncServerSocketModule *module = (ILibAsyncServerSocketModule*)user;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < module->MaxConnection; ++i)
|
||||
{
|
||||
ILibChain_SafeRemoveEx(chain, module->AsyncSockets[i]);
|
||||
}
|
||||
ILibChain_SafeRemoveEx(chain, module);
|
||||
}
|
||||
void ILibAsyncServerSocket_RemoveFromChain(ILibAsyncServerSocket_ServerModule serverModule)
|
||||
{
|
||||
ILibChain_RunOnMicrostackThreadEx(((ILibAsyncServerSocketModule*)serverModule)->ChainLink.ParentChain, ILibAsyncServerSocket_RemoveFromChainSink, serverModule);
|
||||
}
|
||||
|
||||
/*! \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);
|
||||
}
|
||||
#ifndef MICROSTACK_NOTLS
|
||||
void ILibAsyncServerSocket_SSL_SetSink(ILibAsyncServerSocket_ServerModule AsyncServerSocketModule, ILibAsyncServerSocket_OnSSL handler)
|
||||
{
|
||||
((struct ILibAsyncServerSocketModule*)AsyncServerSocketModule)->OnSSLContext = handler;
|
||||
}
|
||||
#endif
|
||||
177
microstack/ILibAsyncServerSocket.h
Normal file
177
microstack/ILibAsyncServerSocket.h
Normal file
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
Copyright 2006 - 2017 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ___ILibAsyncServerSocket___
|
||||
#define ___ILibAsyncServerSocket___
|
||||
|
||||
/*! \file ILibAsyncServerSocket.h
|
||||
\brief MicroStack APIs for TCP Server Functionality
|
||||
*/
|
||||
|
||||
/*! \defgroup ILibAsyncServerSocket ILibAsyncServerSocket Module
|
||||
\{
|
||||
*/
|
||||
|
||||
#if defined(WIN32) || defined(_WIN32_WCE)
|
||||
#include <STDDEF.H>
|
||||
#elif defined(_POSIX)
|
||||
#if !defined(__APPLE__) && !defined(_VX_CPU)
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
#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);
|
||||
#ifndef MICROSTACK_NOTLS
|
||||
typedef void(*ILibAsyncServerSocket_OnSSL)(ILibAsyncServerSocket_ServerModule AsyncServerSocketModule, void* ConnectionToken, SSL* ctx, void **user);
|
||||
void ILibAsyncServerSocket_SSL_SetSink(ILibAsyncServerSocket_ServerModule AsyncServerSocketModule, ILibAsyncServerSocket_OnSSL handler);
|
||||
void* ILibAsyncServerSocket_GetSSL_CTX(ILibAsyncServerSocket_ServerModule ILibAsyncSocketModule);
|
||||
#ifdef MICROSTACK_TLS_DETECT
|
||||
void ILibAsyncServerSocket_SetSSL_CTX(ILibAsyncServerSocket_ServerModule ILibAsyncSocketModule, void *ssl_ctx, int enableTLSDetect);
|
||||
#else
|
||||
void ILibAsyncServerSocket_SetSSL_CTX(ILibAsyncServerSocket_ServerModule ILibAsyncSocketModule, void *ssl_ctx);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
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
|
||||
|
||||
2312
microstack/ILibAsyncSocket.c
Normal file
2312
microstack/ILibAsyncSocket.c
Normal file
File diff suppressed because it is too large
Load Diff
248
microstack/ILibAsyncSocket.h
Normal file
248
microstack/ILibAsyncSocket.h
Normal file
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
Copyright 2006 - 2017 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ___ILibAsyncSocket___
|
||||
#define ___ILibAsyncSocket___
|
||||
|
||||
/*! \file ILibAsyncSocket.h
|
||||
\brief MicroStack APIs for TCP Client Functionality
|
||||
*/
|
||||
|
||||
/*! \defgroup ILibAsyncSocket ILibAsyncSocket Module
|
||||
\{
|
||||
*/
|
||||
|
||||
#if defined(WIN32) || defined(_WIN32_WCE)
|
||||
#include <STDDEF.H>
|
||||
#elif defined(_POSIX)
|
||||
#if !defined(__APPLE__) && !defined(_VX_CPU)
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//#include "ssl.h"
|
||||
#ifndef MICROSTACK_NOTLS
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32_WCE)
|
||||
#ifndef ptrdiff_t
|
||||
#define ptrdiff_t long
|
||||
#endif
|
||||
#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 */
|
||||
#ifndef MICROSTACK_NOTLS
|
||||
ILibAsyncSocket_MemoryOwnership_BIO = 3
|
||||
#endif
|
||||
}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
|
||||
* @{
|
||||
*/
|
||||
#ifndef MICROSTACK_NOTLS
|
||||
#ifdef MICROSTACK_TLS_DETECT
|
||||
int ILibAsyncSocket_IsUsingTls(ILibAsyncSocket_SocketModule AsyncSocketToken);
|
||||
#endif
|
||||
#endif
|
||||
/*! @} */
|
||||
|
||||
extern const int ILibMemory_ASYNCSOCKET_CONTAINERSIZE;
|
||||
#define ILibAsyncSocket_LOCK_OVERRIDE 0x40000000
|
||||
|
||||
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);
|
||||
void ILibAsyncSocket_UpdateCallbacks(ILibAsyncSocket_SocketModule module, ILibAsyncSocket_OnData OnData, ILibAsyncSocket_OnConnect OnConnect, ILibAsyncSocket_OnDisconnect OnDisconnect, ILibAsyncSocket_OnSendOK OnSendOK);
|
||||
|
||||
#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);
|
||||
|
||||
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_MultiWrite(ILibAsyncSocket_SocketModule socketModule, struct sockaddr *remoteAddress, unsigned int count, ...);
|
||||
|
||||
/*! \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_MultiWrite(socketModule, NULL, 1, buffer, length, UserFree)
|
||||
#define ILibAsyncSocket_SendTo(socketModule, buffer, length, remoteAddress, UserFree) ILibAsyncSocket_SendTo_MultiWrite(socketModule, remoteAddress, 1, buffer, length, UserFree)
|
||||
|
||||
void ILibAsyncSocket_Disconnect(ILibAsyncSocket_SocketModule socketModule);
|
||||
void ILibAsyncSocket_GetBuffer(ILibAsyncSocket_SocketModule socketModule, char **buffer, int *BeginPointer, int *EndPointer);
|
||||
|
||||
#if defined(_WIN32_WCE) || 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
|
||||
|
||||
#ifndef MICROSTACK_NOTLS
|
||||
|
||||
//! TLS Mode for OpenSSL Configuration
|
||||
/*! \ingroup TLSGroup */
|
||||
typedef enum ILibAsyncSocket_TLS_Mode
|
||||
{
|
||||
ILibAsyncSocket_TLS_Mode_Client = 0, //!< Client Mode
|
||||
ILibAsyncSocket_TLS_Mode_Server = 1, //!< Server Mode
|
||||
#ifdef MICROSTACK_TLS_DETECT
|
||||
ILibAsyncSocket_TLS_Mode_Server_with_TLSDetectLogic = 2, //!< Server Mode with TLS Detection logic enabled
|
||||
#endif
|
||||
}ILibAsyncSocket_TLS_Mode;
|
||||
|
||||
SSL* ILibAsyncSocket_SetSSLContext(ILibAsyncSocket_SocketModule socketModule, SSL_CTX *ssl_ctx, ILibAsyncSocket_TLS_Mode server);
|
||||
SSL_CTX *ILibAsyncSocket_GetSSLContext(ILibAsyncSocket_SocketModule socketModule);
|
||||
#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);
|
||||
|
||||
#ifndef MICROSTACK_NOTLS
|
||||
X509 *ILibAsyncSocket_SslGetCert(ILibAsyncSocket_SocketModule socketModule);
|
||||
STACK_OF(X509) *ILibAsyncSocket_SslGetCerts(ILibAsyncSocket_SocketModule socketModule);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
311
microstack/ILibAsyncUDPSocket.c
Normal file
311
microstack/ILibAsyncUDPSocket.c
Normal file
@@ -0,0 +1,311 @@
|
||||
/*
|
||||
Copyright 2006 - 2017 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#ifdef MEMORY_CHECK
|
||||
#define MEMCHECK(x) x
|
||||
#else
|
||||
#define MEMCHECK(x)
|
||||
#endif
|
||||
|
||||
#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(_MINCORE)
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include <crtdbg.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 "ILibAsyncUDPSocket.h"
|
||||
#include "ILibAsyncSocket.h"
|
||||
|
||||
#define INET_SOCKADDR_LENGTH(x) ((x==AF_INET6?sizeof(struct sockaddr_in6):sizeof(struct sockaddr_in)))
|
||||
#define INET_SOCKADDR_PORT(x) (x->sa_family==AF_INET6?(unsigned short)(((struct sockaddr_in6*)x)->sin6_port):(unsigned short)(((struct sockaddr_in*)x)->sin_port))
|
||||
#define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR, 12)
|
||||
|
||||
struct ILibAsyncUDPSocket_Data
|
||||
{
|
||||
void *user1;
|
||||
void *user2;
|
||||
|
||||
ILibAsyncSocket_SocketModule UDPSocket;
|
||||
unsigned short BoundPortNumber;
|
||||
|
||||
ILibAsyncUDPSocket_OnData OnData;
|
||||
ILibAsyncUDPSocket_OnSendOK OnSendOK;
|
||||
};
|
||||
|
||||
void ILibAsyncUDPSocket_OnDataSink(ILibAsyncSocket_SocketModule socketModule, char* buffer, int *p_beginPointer, int endPointer, ILibAsyncSocket_OnInterrupt* OnInterrupt, void **user, int *PAUSE)
|
||||
{
|
||||
struct ILibAsyncUDPSocket_Data *data = (struct ILibAsyncUDPSocket_Data*)*user;
|
||||
char RemoteAddress[8 + sizeof(struct sockaddr_in6)];
|
||||
UNREFERENCED_PARAMETER( OnInterrupt );
|
||||
UNREFERENCED_PARAMETER( RemoteAddress );
|
||||
ILibAsyncSocket_GetRemoteInterface(socketModule, (struct sockaddr*)&RemoteAddress);
|
||||
((int*)(RemoteAddress + sizeof(struct sockaddr_in6)))[0] = 4;
|
||||
((int*)(RemoteAddress + sizeof(struct sockaddr_in6)))[1] = 0;
|
||||
|
||||
if (data->OnData != NULL)
|
||||
{
|
||||
data->OnData(
|
||||
socketModule,
|
||||
buffer,
|
||||
endPointer,
|
||||
(struct sockaddr_in6*)&RemoteAddress,
|
||||
data->user1,
|
||||
data->user2,
|
||||
PAUSE);
|
||||
}
|
||||
*p_beginPointer = endPointer;
|
||||
}
|
||||
|
||||
void ILibAsyncUDPSocket_OnSendOKSink(ILibAsyncSocket_SocketModule socketModule, void *user)
|
||||
{
|
||||
struct ILibAsyncUDPSocket_Data *data = (struct ILibAsyncUDPSocket_Data*)user;
|
||||
if (data->OnSendOK!=NULL)
|
||||
{
|
||||
data->OnSendOK(socketModule, data->user1, data->user2);
|
||||
}
|
||||
}
|
||||
|
||||
void ILibAsyncUDPSocket_OnDisconnect(ILibAsyncSocket_SocketModule socketModule, void *user)
|
||||
{
|
||||
UNREFERENCED_PARAMETER( socketModule );
|
||||
free(user);
|
||||
}
|
||||
/*! \fn ILibAsyncUDPSocket_SocketModule ILibAsyncUDPSocket_CreateEx(void *Chain, int BufferSize, int localInterface, unsigned short localPortStartRange, unsigned short localPortEndRange, enum ILibAsyncUDPSocket_Reuse reuse, ILibAsyncUDPSocket_OnData OnData, ILibAsyncUDPSocket_OnSendOK OnSendOK, void *user)
|
||||
\brief Creates a new instance of an ILibAsyncUDPSocket module, using a random port number between \a localPortStartRange and \a localPortEndRange inclusive.
|
||||
\param Chain The chain to add this object to. (Chain must <B>not</B> not be running)
|
||||
\param BufferSize The size of the buffer to use
|
||||
\param localInterface The IP address to bind this socket to, in network order
|
||||
\param localPortStartRange The begin range to select a port number from (host order)
|
||||
\param localPortEndRange The end range to select a port number from (host order)
|
||||
\param reuse Reuse type
|
||||
\param OnData The handler to receive data
|
||||
\param OnSendOK The handler to receive notification that pending sends have completed
|
||||
\param user User object to associate with this object
|
||||
\returns The ILibAsyncUDPSocket_SocketModule handle that was created
|
||||
*/
|
||||
ILibAsyncUDPSocket_SocketModule ILibAsyncUDPSocket_CreateEx(void *Chain, int BufferSize, struct sockaddr *localInterface, enum ILibAsyncUDPSocket_Reuse reuse, ILibAsyncUDPSocket_OnData OnData, ILibAsyncUDPSocket_OnSendOK OnSendOK, void *user)
|
||||
{
|
||||
int off = 0;
|
||||
SOCKET sock;
|
||||
int ra = (int)reuse;
|
||||
void *RetVal = NULL;
|
||||
struct ILibAsyncUDPSocket_Data *data;
|
||||
#ifdef WINSOCK2
|
||||
DWORD dwBytesReturned = 0;
|
||||
BOOL bNewBehavior = FALSE;
|
||||
#endif
|
||||
|
||||
// Initialize the UDP socket data structure
|
||||
data = (struct ILibAsyncUDPSocket_Data*)malloc(sizeof(struct ILibAsyncUDPSocket_Data));
|
||||
if (data == NULL) return NULL;
|
||||
memset(data, 0, sizeof(struct ILibAsyncUDPSocket_Data));
|
||||
data->OnData = OnData;
|
||||
data->OnSendOK = OnSendOK;
|
||||
data->user1 = user;
|
||||
|
||||
// Create a new socket & set REUSE if needed. If it's IPv6, use the same socket for both IPv4 and IPv6.
|
||||
if ((sock = socket(localInterface->sa_family, SOCK_DGRAM, IPPROTO_UDP)) == -1) { free(data); return 0; }
|
||||
if (reuse == ILibAsyncUDPSocket_Reuse_SHARED) if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&ra, sizeof(ra)) != 0) ILIBCRITICALERREXIT(253);
|
||||
#ifdef __APPLE__
|
||||
if (reuse == ILibAsyncUDPSocket_Reuse_SHARED) if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (char*)&ra, sizeof(ra)) != 0) ILIBCRITICALERREXIT(253);
|
||||
#endif
|
||||
if (localInterface->sa_family == AF_INET6) if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&off, sizeof(off)) != 0) ILIBCRITICALERREXIT(253);
|
||||
|
||||
// Attempt to bind the UDP socket
|
||||
#ifdef WIN32
|
||||
if ( bind(sock, localInterface, INET_SOCKADDR_LENGTH(localInterface->sa_family)) != 0 ) { closesocket(sock); free(data); return NULL; }
|
||||
#else
|
||||
if ( bind(sock, localInterface, INET_SOCKADDR_LENGTH(localInterface->sa_family)) != 0 ) { close(sock); free(data); return NULL; }
|
||||
#endif
|
||||
|
||||
#ifdef WINSOCK2
|
||||
WSAIoctl(sock, SIO_UDP_CONNRESET, &bNewBehavior, sizeof(bNewBehavior), NULL, 0, &dwBytesReturned, NULL, NULL);
|
||||
#endif
|
||||
|
||||
// Set the BoundPortNumber
|
||||
if (localInterface->sa_family == AF_INET6) { data->BoundPortNumber = ntohs(((struct sockaddr_in6*)localInterface)->sin6_port); } else { data->BoundPortNumber = ntohs(((struct sockaddr_in*)localInterface)->sin_port); }
|
||||
|
||||
// Create an Async Socket to handle the data
|
||||
RetVal = ILibCreateAsyncSocketModule(Chain, BufferSize, &ILibAsyncUDPSocket_OnDataSink, NULL, &ILibAsyncUDPSocket_OnDisconnect, &ILibAsyncUDPSocket_OnSendOKSink);
|
||||
if (RetVal == NULL)
|
||||
{
|
||||
#if defined(WIN32) || defined(_WIN32_WCE)
|
||||
closesocket(sock);
|
||||
#else
|
||||
close(sock);
|
||||
#endif
|
||||
free(data);
|
||||
return NULL;
|
||||
}
|
||||
ILibAsyncSocket_UseThisSocket(RetVal, sock, &ILibAsyncUDPSocket_OnDisconnect, data);
|
||||
return RetVal; // Klockwork claims we could be losing the resource acquired with the call to socket(), however, we aren't becuase we are saving it with the above call to ILibAsyncSocket_UseThisSocket()
|
||||
}
|
||||
|
||||
SOCKET ILibAsyncUDPSocket_GetSocket(ILibAsyncUDPSocket_SocketModule module)
|
||||
{
|
||||
return *((SOCKET*)ILibAsyncSocket_GetSocket(module));
|
||||
}
|
||||
|
||||
void ILibAsyncUDPSocket_SetBroadcast(ILibAsyncSocket_SocketModule module, int enable)
|
||||
{
|
||||
#if defined(WIN32) || defined(_WIN32_WCE)
|
||||
SOCKET s = *((SOCKET*)ILibAsyncSocket_GetSocket(module));
|
||||
#else
|
||||
int s = *((int*)ILibAsyncSocket_GetSocket(module));
|
||||
#endif
|
||||
|
||||
setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char*)&enable, sizeof(enable));
|
||||
}
|
||||
|
||||
|
||||
void ILibAsyncUDPSocket_DropMulticastGroupV4(ILibAsyncUDPSocket_SocketModule module, struct sockaddr_in *multicastAddr, struct sockaddr *localAddr)
|
||||
{
|
||||
struct ip_mreq mreq;
|
||||
#if defined(WIN32) || defined(_WIN32_WCE)
|
||||
SOCKET s = *((SOCKET*)ILibAsyncSocket_GetSocket(module));
|
||||
#else
|
||||
int s = *((int*)ILibAsyncSocket_GetSocket(module));
|
||||
#endif
|
||||
|
||||
// We start with the multicast structure
|
||||
memcpy_s(&mreq.imr_multiaddr, sizeof(mreq.imr_multiaddr), &(((struct sockaddr_in*)multicastAddr)->sin_addr), sizeof(mreq.imr_multiaddr));
|
||||
#ifdef WIN32
|
||||
mreq.imr_interface.s_addr = ((struct sockaddr_in*)localAddr)->sin_addr.S_un.S_addr;
|
||||
#else
|
||||
mreq.imr_interface.s_addr = ((struct sockaddr_in*)localAddr)->sin_addr.s_addr;
|
||||
#endif
|
||||
setsockopt(s, IPPROTO_IP, IP_DROP_MEMBERSHIP, (char*)&mreq, sizeof(mreq));
|
||||
}
|
||||
|
||||
/*! \fn int ILibAsyncUDPSocket_JoinMulticastGroup(ILibAsyncUDPSocket_SocketModule module, int localInterface, int remoteInterface)
|
||||
\brief Joins a multicast group
|
||||
\param module The ILibAsyncUDPSocket_SocketModule to join the multicast group
|
||||
\param localInterface The local IP address in network order, to join the multicast group
|
||||
\param remoteInterface The multicast ip address in network order, to join
|
||||
\returns 0 = Success, Nonzero = Failure
|
||||
*/
|
||||
void ILibAsyncUDPSocket_JoinMulticastGroupV4(ILibAsyncUDPSocket_SocketModule module, struct sockaddr_in *multicastAddr, struct sockaddr *localAddr)
|
||||
{
|
||||
struct ip_mreq mreq;
|
||||
#if defined(WIN32) || defined(_WIN32_WCE)
|
||||
SOCKET s = *((SOCKET*)ILibAsyncSocket_GetSocket(module));
|
||||
#else
|
||||
int s = *((int*)ILibAsyncSocket_GetSocket(module));
|
||||
#endif
|
||||
|
||||
// We start with the multicast structure
|
||||
memcpy_s(&mreq.imr_multiaddr, sizeof(mreq.imr_multiaddr), &(((struct sockaddr_in*)multicastAddr)->sin_addr), sizeof(mreq.imr_multiaddr));
|
||||
#ifdef WIN32
|
||||
mreq.imr_interface.s_addr = ((struct sockaddr_in*)localAddr)->sin_addr.S_un.S_addr;
|
||||
#else
|
||||
mreq.imr_interface.s_addr = ((struct sockaddr_in*)localAddr)->sin_addr.s_addr;
|
||||
#endif
|
||||
setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&mreq, sizeof(mreq));
|
||||
}
|
||||
|
||||
void ILibAsyncUDPSocket_JoinMulticastGroupV6(ILibAsyncUDPSocket_SocketModule module, struct sockaddr_in6 *multicastAddr, int ifIndex)
|
||||
{
|
||||
struct ipv6_mreq mreq6;
|
||||
#if defined(WIN32) || defined(_WIN32_WCE)
|
||||
SOCKET s = *((SOCKET*)ILibAsyncSocket_GetSocket(module));
|
||||
#else
|
||||
int s = *((int*)ILibAsyncSocket_GetSocket(module));
|
||||
#endif
|
||||
|
||||
memcpy_s(&mreq6.ipv6mr_multiaddr, sizeof(mreq6.ipv6mr_multiaddr), &(((struct sockaddr_in6*)multicastAddr)->sin6_addr), sizeof(mreq6.ipv6mr_multiaddr));
|
||||
mreq6.ipv6mr_interface = ifIndex;
|
||||
setsockopt(s, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char*)&mreq6, sizeof(mreq6)); // IPV6_ADD_MEMBERSHIP
|
||||
}
|
||||
|
||||
void ILibAsyncUDPSocket_DropMulticastGroupV6(ILibAsyncUDPSocket_SocketModule module, struct sockaddr_in6 *multicastAddr, int ifIndex)
|
||||
{
|
||||
struct ipv6_mreq mreq6;
|
||||
#if defined(WIN32) || defined(_WIN32_WCE)
|
||||
SOCKET s = *((SOCKET*)ILibAsyncSocket_GetSocket(module));
|
||||
#else
|
||||
int s = *((int*)ILibAsyncSocket_GetSocket(module));
|
||||
#endif
|
||||
|
||||
memcpy_s(&mreq6.ipv6mr_multiaddr, sizeof(mreq6.ipv6mr_multiaddr), &(((struct sockaddr_in6*)multicastAddr)->sin6_addr), sizeof(mreq6.ipv6mr_multiaddr));
|
||||
mreq6.ipv6mr_interface = ifIndex;
|
||||
setsockopt(s, IPPROTO_IPV6, IPV6_LEAVE_GROUP, (char*)&mreq6, sizeof(mreq6)); // IPV6_ADD_MEMBERSHIP
|
||||
}
|
||||
/*! \fn int ILibAsyncUDPSocket_SetMulticastInterface(ILibAsyncUDPSocket_SocketModule module, int localInterface)
|
||||
\brief Sets the local interface to use, when multicasting
|
||||
\param module The ILibAsyncUDPSocket_SocketModule handle to set the interface on
|
||||
\param localInterface The local IP address in network order, to use when multicasting
|
||||
\returns 0 = Success, Nonzero = Failure
|
||||
*/
|
||||
void ILibAsyncUDPSocket_SetMulticastInterface(ILibAsyncUDPSocket_SocketModule module, struct sockaddr *localInterface)
|
||||
{
|
||||
#if defined(WIN32)
|
||||
SOCKET s = *((SOCKET*)ILibAsyncSocket_GetSocket(module));
|
||||
#else
|
||||
int s = *((int*)ILibAsyncSocket_GetSocket(module));
|
||||
#endif
|
||||
if (localInterface->sa_family == AF_INET6)
|
||||
{
|
||||
// Uses the interface index of the desired outgoing interface
|
||||
if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_IF, (char*)&(((struct sockaddr_in6*)localInterface)->sin6_scope_id), sizeof(((struct sockaddr_in6*) localInterface)->sin6_scope_id)) != 0) ILIBCRITICALERREXIT(253);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, (char*)&(((struct sockaddr_in*)localInterface)->sin_addr.s_addr), sizeof(struct in_addr)) != 0) ILIBCRITICALERREXIT(253);
|
||||
}
|
||||
}
|
||||
|
||||
/*! \fn int ILibAsyncUDPSocket_SetMulticastTTL(ILibAsyncUDPSocket_SocketModule module, unsigned char TTL)
|
||||
\brief Sets the Multicast TTL value
|
||||
\param module The ILibAsyncUDPSocket_SocketModule handle to set the Multicast TTL value
|
||||
\param TTL The Multicast-TTL value to use
|
||||
\returns 0 = Success, Nonzero = Failure
|
||||
*/
|
||||
void ILibAsyncUDPSocket_SetMulticastTTL(ILibAsyncUDPSocket_SocketModule module, int TTL)
|
||||
{
|
||||
struct sockaddr_in6 localAddress;
|
||||
#if defined(__SYMBIAN32__)
|
||||
return 0;
|
||||
#else
|
||||
#if defined(WIN32) || defined(_WIN32_WCE)
|
||||
SOCKET s = *((SOCKET*)ILibAsyncSocket_GetSocket(module));
|
||||
#else
|
||||
int s = *((int*)ILibAsyncSocket_GetSocket(module));
|
||||
#endif
|
||||
ILibAsyncSocket_GetLocalInterface(module, (struct sockaddr*)&localAddress);
|
||||
if (setsockopt(s, localAddress.sin6_family == PF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP, localAddress.sin6_family == PF_INET6 ? IPV6_MULTICAST_HOPS : IP_MULTICAST_TTL, (char*)&TTL, sizeof(TTL)) != 0) ILIBCRITICALERREXIT(253);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ILibAsyncUDPSocket_SetMulticastLoopback(ILibAsyncUDPSocket_SocketModule module, int loopback)
|
||||
{
|
||||
struct sockaddr_in6 localAddress;
|
||||
#if defined(WIN32) || defined(_WIN32_WCE)
|
||||
SOCKET s = *((SOCKET*)ILibAsyncSocket_GetSocket(module));
|
||||
#else
|
||||
int s = *((int*)ILibAsyncSocket_GetSocket(module));
|
||||
#endif
|
||||
|
||||
ILibAsyncSocket_GetLocalInterface(module, (struct sockaddr*)&localAddress);
|
||||
if (setsockopt(s, localAddress.sin6_family == PF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP, localAddress.sin6_family == PF_INET6 ? IPV6_MULTICAST_LOOP : IP_MULTICAST_LOOP, (char*)&loopback, sizeof(loopback)) != 0) ILIBCRITICALERREXIT(253);
|
||||
}
|
||||
158
microstack/ILibAsyncUDPSocket.h
Normal file
158
microstack/ILibAsyncUDPSocket.h
Normal file
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
Copyright 2006 - 2017 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ___ILibAsyncUDPSocket___
|
||||
#define ___ILibAsyncUDPSocket___
|
||||
|
||||
/*! \file ILibAsyncUDPSocket.h
|
||||
\brief MicroStack APIs for UDP Functionality
|
||||
*/
|
||||
|
||||
/*! \defgroup ILibAsyncUDPSocket ILibAsyncUDPSocket Module
|
||||
\{
|
||||
*/
|
||||
|
||||
#if defined(WIN32) || defined(_WIN32_WCE)
|
||||
#include <STDDEF.H>
|
||||
#elif defined(_POSIX)
|
||||
#if !defined(__APPLE__) && !defined(_VX_CPU)
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "ILibAsyncSocket.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum ILibAsyncUDPSocket_Reuse
|
||||
{
|
||||
ILibAsyncUDPSocket_Reuse_EXCLUSIVE = 0, /*!< A socket is to be bound for exclusive access */
|
||||
ILibAsyncUDPSocket_Reuse_SHARED = 1 /*!< A socket is to be bound for shared access */
|
||||
}ILibAsyncUDPSocket_Reuse;
|
||||
|
||||
/*! \typedef ILibAsyncUDPSocket_SocketModule
|
||||
\brief The handle for an ILibAsyncUDPSocket module
|
||||
*/
|
||||
typedef void* ILibAsyncUDPSocket_SocketModule;
|
||||
/*! \typedef ILibAsyncUDPSocket_OnData
|
||||
\brief The handler that is called when data is received
|
||||
\param socketModule The \a ILibAsyncUDPSocket_SocketModule handle that received data
|
||||
\param buffer The buffer that contains the read data
|
||||
\param bufferLength The amount of data that was read
|
||||
\param remoteInterface The IP address of the source, in network order
|
||||
\param remotePort The port number of the source, in host order
|
||||
\param user User object associated with this module
|
||||
\param user2 User2 object associated with this module
|
||||
\param[out] PAUSE Set this flag to non-zero, to prevent more data from being read
|
||||
*/
|
||||
typedef void(*ILibAsyncUDPSocket_OnData)(ILibAsyncUDPSocket_SocketModule socketModule, char* buffer, int bufferLength, struct sockaddr_in6 *remoteInterface, void *user, void *user2, int *PAUSE);
|
||||
/*! \typedef ILibAsyncUDPSocket_OnSendOK
|
||||
\brief Handler for when pending send operations have completed
|
||||
\par
|
||||
This handler will only be called if a call to \a ILibAsyncUDPSocket_SendTo returned a value greater
|
||||
than 0, which indicates that not all of the data could be sent.
|
||||
<P><B>Note:</B> On most systems, UDP data that cannot be sent will be dropped, which means that this handler
|
||||
may actually never be called.
|
||||
\param socketModule The \a ILibAsyncUDPSocket_SocketModule whos pending sends have completed
|
||||
\param user1 User object that was associated with this connection
|
||||
\param user2 User2 object that was associated with this connection
|
||||
*/
|
||||
typedef void(*ILibAsyncUDPSocket_OnSendOK)(ILibAsyncUDPSocket_SocketModule socketModule, void *user1, void *user2);
|
||||
|
||||
ILibAsyncUDPSocket_SocketModule ILibAsyncUDPSocket_CreateEx(void *Chain, int BufferSize, struct sockaddr *localInterface, enum ILibAsyncUDPSocket_Reuse reuse, ILibAsyncUDPSocket_OnData OnData, ILibAsyncUDPSocket_OnSendOK OnSendOK, void *user);
|
||||
|
||||
/*! \def ILibAsyncUDPSocket_Create
|
||||
\brief Creates a new instance of an ILibAsyncUDPSocket module.
|
||||
\param Chain The chain to add this object to. (Chain must <B>not</B> not be running)
|
||||
\param BufferSize The size of the buffer to use
|
||||
\param localInterface The IP address to bind this socket to, in network order
|
||||
\param localPort The port to bind this socket to, in host order. (0 = Random IANA specified generic port)
|
||||
\param reuse Reuse type
|
||||
\param OnData The handler to receive data
|
||||
\param OnSendOK The handler to receive notification that pending sends have completed
|
||||
\param user User object to associate with this object
|
||||
\returns The ILibAsyncUDPSocket_SocketModule handle that was created
|
||||
*/
|
||||
//#define ILibAsyncUDPSocket_Create(Chain, BufferSize, localInterface, localInterfaceSize, reuse, OnData , OnSendOK, user)localPort==0?ILibAsyncUDPSocket_CreateEx(Chain, BufferSize, localInterface, 50000, 65500, reuse, OnData, OnSendOK, user):ILibAsyncUDPSocket_CreateEx(Chain, BufferSize, localInterface, localPort, localPort, reuse, OnData, OnSendOK, user)
|
||||
|
||||
void ILibAsyncUDPSocket_JoinMulticastGroupV4(ILibAsyncUDPSocket_SocketModule module, struct sockaddr_in *multicastAddr, struct sockaddr *localAddr);
|
||||
void ILibAsyncUDPSocket_JoinMulticastGroupV6(ILibAsyncUDPSocket_SocketModule module, struct sockaddr_in6 *multicastAddr, int ifIndex);
|
||||
void ILibAsyncUDPSocket_DropMulticastGroupV4(ILibAsyncUDPSocket_SocketModule module, struct sockaddr_in *multicastAddr, struct sockaddr *localAddr);
|
||||
void ILibAsyncUDPSocket_DropMulticastGroupV6(ILibAsyncUDPSocket_SocketModule module, struct sockaddr_in6 *multicastAddr, int ifIndex);
|
||||
void ILibAsyncUDPSocket_SetMulticastInterface(ILibAsyncUDPSocket_SocketModule module, struct sockaddr *localInterface);
|
||||
void ILibAsyncUDPSocket_SetMulticastTTL(ILibAsyncUDPSocket_SocketModule module, int TTL);
|
||||
void ILibAsyncUDPSocket_SetMulticastLoopback(ILibAsyncUDPSocket_SocketModule module, int loopback);
|
||||
|
||||
void ILibAsyncUDPSocket_SetBroadcast(ILibAsyncSocket_SocketModule module, int enable);
|
||||
|
||||
/*! \def ILibAsyncUDPSocket_GetPendingBytesToSend
|
||||
\brief Returns the number of bytes that are pending to be sent
|
||||
\param socketModule The ILibAsyncUDPSocket_SocketModule handle to query
|
||||
\returns Number of pending bytes
|
||||
*/
|
||||
#define ILibAsyncUDPSocket_GetPendingBytesToSend(socketModule) ILibAsyncSocket_GetPendingBytesToSend(socketModule)
|
||||
/*! \def ILibAsyncUDPSocket_GetTotalBytesSent
|
||||
\brief Returns the total number of bytes that have been sent, since the last reset
|
||||
\param socketModule The ILibAsyncUDPSocket_SocketModule handle to query
|
||||
\returns Number of bytes sent
|
||||
*/
|
||||
#define ILibAsyncUDPSocket_GetTotalBytesSent(socketModule) ILibAsyncSocket_GetTotalBytesSent(socketModule)
|
||||
/*! \def ILibAsyncUDPSocket_ResetTotalBytesSent
|
||||
\brief Resets the total bytes sent counter
|
||||
\param socketModule The ILibAsyncUDPSocket_SocketModule handle to reset
|
||||
*/
|
||||
#define ILibAsyncUDPSocket_ResetTotalBytesSent(socketModule) ILibAsyncSocket_ResetTotalBytesSent(socketModule)
|
||||
|
||||
|
||||
/*! \def ILibAsyncUDPSocket_SendTo
|
||||
\brief Sends a UDP packet
|
||||
\param socketModule The ILibAsyncUDPSocket_SocketModule handle to send a packet on
|
||||
\param remoteInterface The IP address in network order, to send the packet to
|
||||
\param remotePort The port numer in host order to send the packet to
|
||||
\param buffer The buffer to send
|
||||
\param length The length of \a buffer
|
||||
\param UserFree The ILibAsyncSocket_MemoryOwnership flag indicating how the memory in \a buffer is to be handled
|
||||
\returns The ILibAsyncSocket_SendStatus status of the packet that was sent
|
||||
*/
|
||||
#define ILibAsyncUDPSocket_SendTo(socketModule, remoteInterface, buffer, length, UserFree) ILibAsyncSocket_SendTo(socketModule, buffer, length, remoteInterface, UserFree)
|
||||
|
||||
/*! \def ILibAsyncUDPSocket_GetLocalInterface
|
||||
\brief Get's the bounded IP address in network order
|
||||
\param socketModule The ILibAsyncUDPSocket_SocketModule to query
|
||||
\returns The local bounded IP address in network order
|
||||
*/
|
||||
#define ILibAsyncUDPSocket_GetLocalInterface(socketModule, localAddress) ILibAsyncSocket_GetLocalInterface(socketModule, localAddress)
|
||||
#define ILibAsyncUDPSocket_SetLocalInterface(socketModule, localAddress) ILibAsyncSocket_SetLocalInterface(socketModule, localAddress)
|
||||
|
||||
/*! \def ILibAsyncUDPSocket_GetLocalPort
|
||||
\brief Get's the bounded port in host order
|
||||
\param socketModule The ILibAsyncUDPSocket_SocketModule to query
|
||||
\returns The local bounded port in host order
|
||||
*/
|
||||
#define ILibAsyncUDPSocket_GetLocalPort(socketModule) ILibAsyncSocket_GetLocalPort(socketModule)
|
||||
|
||||
#define ILibAsyncUDPSocket_Resume(socketModule) ILibAsyncSocket_Resume(socketModule)
|
||||
|
||||
SOCKET ILibAsyncUDPSocket_GetSocket(ILibAsyncUDPSocket_SocketModule module);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
936
microstack/ILibCrypto.c
Normal file
936
microstack/ILibCrypto.c
Normal file
@@ -0,0 +1,936 @@
|
||||
#if defined(WIN32) && !defined(_WIN32_WCE)
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include <crtdbg.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include "ILibCrypto.h"
|
||||
|
||||
#ifndef MICROSTACK_NOTLS
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/pkcs7.h>
|
||||
#include <openssl/pkcs12.h>
|
||||
#include <openssl/conf.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include <openssl/md5.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/hmac.h>
|
||||
#else
|
||||
#include "md5.h"
|
||||
#include "sha1.h"
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
char utils_HexTable[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' };
|
||||
char utils_HexTable2[16] = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' };
|
||||
|
||||
void __fastcall util_md5(char* data, int datalen, char* result)
|
||||
{
|
||||
MD5_CTX c;
|
||||
MD5_Init(&c);
|
||||
MD5_Update(&c, data, datalen);
|
||||
MD5_Final((unsigned char*)result, &c);
|
||||
}
|
||||
void __fastcall util_md5hex(char* data, int datalen, char *out)
|
||||
{
|
||||
int i = 0;
|
||||
unsigned char *temp = (unsigned char*)out;
|
||||
MD5_CTX mdContext;
|
||||
unsigned char digest[16];
|
||||
|
||||
MD5_Init(&mdContext);
|
||||
MD5_Update(&mdContext, (unsigned char *)data, datalen);
|
||||
MD5_Final(digest, &mdContext);
|
||||
|
||||
for (i = 0; i < HALF_NONCE_SIZE; i++)
|
||||
{
|
||||
*(temp++) = utils_HexTable2[(unsigned char)digest[i] >> 4];
|
||||
*(temp++) = utils_HexTable2[(unsigned char)digest[i] & 0x0F];
|
||||
}
|
||||
|
||||
*temp = '\0';
|
||||
}
|
||||
void __fastcall util_sha1(char* data, int datalen, char* result)
|
||||
{
|
||||
SHA_CTX c;
|
||||
SHA1_Init(&c);
|
||||
SHA1_Update(&c, data, datalen);
|
||||
SHA1_Final((unsigned char*)result, &c);
|
||||
result[20] = 0;
|
||||
}
|
||||
|
||||
void __fastcall util_sha256(char* data, int datalen, char* result)
|
||||
{
|
||||
SHA256_CTX c;
|
||||
SHA256_Init(&c);
|
||||
SHA256_Update(&c, data, datalen);
|
||||
SHA256_Final((unsigned char*)result, &c);
|
||||
}
|
||||
int __fastcall util_sha256file(char* filename, char* result)
|
||||
{
|
||||
FILE *pFile = NULL;
|
||||
SHA256_CTX c;
|
||||
size_t len = 0;
|
||||
char *buf = NULL;
|
||||
|
||||
if (filename == NULL) return -1;
|
||||
#ifdef WIN32
|
||||
fopen_s(&pFile, filename, "rbN");
|
||||
#else
|
||||
pFile = fopen(filename, "rb");
|
||||
#endif
|
||||
if (pFile == NULL) goto error;
|
||||
SHA256_Init(&c);
|
||||
if ((buf = (char*)malloc(4096)) == NULL) goto error;
|
||||
while ((len = fread(buf, 1, 4096, pFile)) > 0) SHA256_Update(&c, buf, len);
|
||||
free(buf);
|
||||
buf = NULL;
|
||||
fclose(pFile);
|
||||
pFile = NULL;
|
||||
SHA256_Final((unsigned char*)result, &c);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
if (buf != NULL) free(buf);
|
||||
if (pFile != NULL) fclose(pFile);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Frees a block of memory returned from this module.
|
||||
void __fastcall util_free(char* ptr)
|
||||
{
|
||||
free(ptr);
|
||||
//ptr = NULL;
|
||||
}
|
||||
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;
|
||||
}
|
||||
char* __fastcall util_tohex_lower(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_HexTable2[((unsigned char)data[i]) >> 4];
|
||||
*(p++) = utils_HexTable2[((unsigned char)data[i]) & 0x0F];
|
||||
}
|
||||
*p = 0;
|
||||
return out;
|
||||
}
|
||||
char* __fastcall util_tohex2(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];
|
||||
if (i + 1<len)
|
||||
{
|
||||
*(p++) = ':';
|
||||
}
|
||||
}
|
||||
*p = 0;
|
||||
return out;
|
||||
}
|
||||
// Convert hex string to int
|
||||
int __fastcall util_hexToint(char *hexString, int hexStringLength)
|
||||
{
|
||||
int i, res = 0;
|
||||
|
||||
// Ignore the leading zeroes
|
||||
while (*hexString == '0' && hexStringLength > 0) { hexString++; hexStringLength--; }
|
||||
|
||||
// Process the rest of the string
|
||||
for (i = 0; i < hexStringLength; i++)
|
||||
{
|
||||
if (hexString[i] >= '0' && hexString[i] <= '9') { res = (res << 4) + (hexString[i] - '0'); }
|
||||
else if (hexString[i] >= 'a' && hexString[i] <= 'f') { res = (res << 4) + (hexString[i] - 'a' + 10); }
|
||||
else if (hexString[i] >= 'A' && hexString[i] <= 'F') { res = (res << 4) + (hexString[i] - 'A' + 10); }
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// Convert hex string to int
|
||||
int __fastcall util_hexToBuf(char *hexString, int hexStringLength, char* output)
|
||||
{
|
||||
int i, x = hexStringLength / 2;
|
||||
for (i = 0; i < x; i++) { output[i] = (char)util_hexToint(hexString + (i * 2), 2); }
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
// Generates a random string of data. TODO: Use Hardware RNG if possible
|
||||
#ifdef MICROSTACK_NOTLS
|
||||
int util_random_seeded = 0;
|
||||
#endif
|
||||
void __fastcall util_random(int length, char* result)
|
||||
{
|
||||
#ifndef MICROSTACK_NOTLS
|
||||
RAND_bytes((unsigned char*)result, length);
|
||||
#else
|
||||
short val;
|
||||
int i;
|
||||
|
||||
if (util_random_seeded == 0)
|
||||
{
|
||||
time_t t;
|
||||
srand((unsigned int)time(&t));
|
||||
util_random_seeded = 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < length; i += 2)
|
||||
{
|
||||
val = rand();
|
||||
memcpy_s(result + i, length - i, &val, (length - i) >= 2 ? 2 : (length - i));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Generates a random text string, useful for HTTP nonces.
|
||||
void __fastcall util_randomtext(int length, char* result)
|
||||
{
|
||||
int l;
|
||||
util_random(length, result);
|
||||
for (l = 0; l<length; l++) result[l] = (unsigned char)((((unsigned char)result[l]) % 10) + '0');
|
||||
}
|
||||
|
||||
|
||||
size_t __fastcall util_writefile(char* filename, char* data, int datalen)
|
||||
{
|
||||
FILE * pFile = NULL;
|
||||
size_t count = 0;
|
||||
|
||||
#ifdef WIN32
|
||||
fopen_s(&pFile, filename, "wbN");
|
||||
#else
|
||||
pFile = fopen(filename, "wb");
|
||||
#endif
|
||||
|
||||
if (pFile != NULL)
|
||||
{
|
||||
count = fwrite(data, datalen, 1, pFile);
|
||||
fclose(pFile);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
size_t __fastcall util_appendfile(char* filename, char* data, int datalen)
|
||||
{
|
||||
FILE * pFile = NULL;
|
||||
size_t count = 0;
|
||||
|
||||
#ifdef WIN32
|
||||
fopen_s(&pFile, filename, "abN");
|
||||
#else
|
||||
pFile = fopen(filename, "ab");
|
||||
#endif
|
||||
|
||||
if (pFile != NULL)
|
||||
{
|
||||
count = fwrite(data, datalen, 1, pFile);
|
||||
fclose(pFile);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
// Read a file into memory up to maxlen. If *data is NULL, a new buffer is allocated otherwise, the given one is used.
|
||||
size_t __fastcall util_readfile(char* filename, char** data, size_t maxlen)
|
||||
{
|
||||
FILE *pFile = NULL;
|
||||
size_t count = 0;
|
||||
size_t len = 0;
|
||||
size_t r = 1;
|
||||
if (filename == NULL) return 0;
|
||||
|
||||
#ifdef WIN32
|
||||
fopen_s(&pFile, filename, "rbN");
|
||||
#else
|
||||
pFile = fopen(filename, "rb");
|
||||
#endif
|
||||
|
||||
if (pFile != NULL)
|
||||
{
|
||||
// If *data is null, we need to allocate memory to read the data. Start by getting the size of the file.
|
||||
if (*data == NULL)
|
||||
{
|
||||
fseek(pFile, 0, SEEK_END);
|
||||
count = ftell(pFile);
|
||||
if (count > maxlen) count = maxlen;
|
||||
fseek(pFile, 0, SEEK_SET);
|
||||
*data = (char*)malloc(count + 1);
|
||||
if (*data == NULL) { fclose(pFile); return 0; }
|
||||
}
|
||||
else { count = maxlen - 1; }
|
||||
while (r != 0 && len < count)
|
||||
{
|
||||
r = fread(*data, 1, count - len, pFile);
|
||||
len += r;
|
||||
}
|
||||
(*data)[len] = 0;
|
||||
fclose(pFile);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
#ifdef _POSIX
|
||||
// This method reads a stream where the length of the file can't be determined. Useful in POSIX only
|
||||
int __fastcall util_readfile2(char* filename, char** data)
|
||||
{
|
||||
FILE * pFile;
|
||||
int count = 0;
|
||||
int len = 0;
|
||||
*data = NULL;
|
||||
if (filename == NULL) return 0;
|
||||
|
||||
pFile = fopen(filename, "rb");
|
||||
if (pFile != NULL)
|
||||
{
|
||||
*data = malloc(1024);
|
||||
if (*data == NULL) { fclose(pFile); return 0; }
|
||||
do
|
||||
{
|
||||
len = (int)fread((*data) + count, 1, 1023, pFile);
|
||||
count += len;
|
||||
if (len == 1023) *data = realloc(*data, count + 1024);
|
||||
} while (len == 100);
|
||||
(*data)[count] = 0;
|
||||
fclose(pFile);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
#endif
|
||||
|
||||
int __fastcall util_deletefile(char* filename)
|
||||
{
|
||||
if (filename == NULL) return 0;
|
||||
return remove(filename);
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
// Really fast CRC-like method. Used for the KVM.
|
||||
int __fastcall util_crc(unsigned char *buffer, int len, int initial_value)
|
||||
{
|
||||
int hval = initial_value;
|
||||
int *bp = (int*)buffer;
|
||||
int *be = bp + (len >> 2);
|
||||
while (bp < be)
|
||||
{
|
||||
//hval *= 0x01000193;
|
||||
hval += (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) + (hval << 24);
|
||||
hval ^= *bp++;
|
||||
}
|
||||
// TODO: Handle left over bytes (len % 4)
|
||||
return hval;
|
||||
}
|
||||
#ifdef _MINCORE
|
||||
BOOL util_MoveFile(_In_ LPCTSTR lpExistingFileName, _In_ LPCTSTR lpNewFileName)
|
||||
{
|
||||
size_t convertedChars = 0;
|
||||
wchar_t lpExistingFileNameW[MAX_PATH];
|
||||
wchar_t lpNewFileNameW[MAX_PATH];
|
||||
mbstowcs_s(&convertedChars, lpExistingFileNameW, MAX_PATH, (const char*)lpExistingFileName, MAX_PATH);
|
||||
mbstowcs_s(&convertedChars, lpNewFileNameW, MAX_PATH, (const char*)lpNewFileName, MAX_PATH);
|
||||
return MoveFileExW(lpExistingFileNameW, lpNewFileNameW, 0);
|
||||
}
|
||||
|
||||
BOOL util_CopyFile(_In_ LPCSTR lpExistingFileName, _In_ LPCSTR lpNewFileName, _In_ BOOL bFailIfExists)
|
||||
{
|
||||
size_t convertedChars = 0;
|
||||
wchar_t lpExistingFileNameW[MAX_PATH];
|
||||
wchar_t lpNewFileNameW[MAX_PATH];
|
||||
mbstowcs_s(&convertedChars, lpExistingFileNameW, MAX_PATH, (const char*)lpExistingFileName, MAX_PATH);
|
||||
mbstowcs_s(&convertedChars, lpNewFileNameW, MAX_PATH, (const char*)lpNewFileName, MAX_PATH);
|
||||
return (CopyFile2(lpExistingFileNameW, lpNewFileNameW, NULL) == S_OK);
|
||||
}
|
||||
#else
|
||||
BOOL util_MoveFile(_In_ LPCSTR lpExistingFileName, _In_ LPCSTR lpNewFileName) { return MoveFileA(lpExistingFileName, lpNewFileName); }
|
||||
BOOL util_CopyFile(_In_ LPCSTR lpExistingFileName, _In_ LPCSTR lpNewFileName, _In_ BOOL bFailIfExists) { return CopyFileA(lpExistingFileName, lpNewFileName, bFailIfExists); }
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifndef MICROSTACK_NOTLS
|
||||
// Setup OpenSSL
|
||||
int InitCounter = 0;
|
||||
void __fastcall util_openssl_init()
|
||||
{
|
||||
char* tbuf[64];
|
||||
#if defined(WIN32)
|
||||
HMODULE g_hAdvLib = NULL;
|
||||
BOOLEAN(APIENTRY *g_CryptGenRandomPtr)(void*, ULONG) = NULL;
|
||||
#endif
|
||||
#ifdef _POSIX
|
||||
int l;
|
||||
#endif
|
||||
|
||||
++InitCounter;
|
||||
if (InitCounter > 1) { return; }
|
||||
|
||||
SSL_library_init(); // TWO LEAKS COMING FROM THIS LINE. Seems to be a well known OpenSSL problem.
|
||||
SSL_load_error_strings();
|
||||
ERR_load_crypto_strings(); // ONE LEAK IN LINUX
|
||||
|
||||
OpenSSL_add_all_algorithms(); // OpenSSL 1.1
|
||||
OpenSSL_add_all_ciphers(); // OpenSSL 1.1
|
||||
OpenSSL_add_all_digests(); // OpenSSL 1.1
|
||||
|
||||
// Add more random seeding in Windows (This is probably useful since OpenSSL in Windows has weaker seeding)
|
||||
#if defined(WIN32) && !defined(_MINCORE)
|
||||
//RAND_screen(); // On Windows, add more random seeding using a screen dump (this is very expensive).
|
||||
if ((g_hAdvLib = LoadLibrary(TEXT("ADVAPI32.DLL"))) != 0) g_CryptGenRandomPtr = (BOOLEAN(APIENTRY *)(void*, ULONG))GetProcAddress(g_hAdvLib, "SystemFunction036");
|
||||
if (g_CryptGenRandomPtr != 0 && g_CryptGenRandomPtr(tbuf, 64) != 0) RAND_add(tbuf, 64, 64); // Use this high quality random as added seeding
|
||||
if (g_hAdvLib != NULL) FreeLibrary(g_hAdvLib);
|
||||
#endif
|
||||
|
||||
// Add more random seeding in Linux (May be overkill since OpenSSL already uses /dev/urandom)
|
||||
#ifdef _POSIX
|
||||
// Under Linux we use "/dev/urandom" if available. This is the best source of random on Linux & variants
|
||||
FILE *pFile = fopen("/dev/urandom", "rb");
|
||||
if (pFile != NULL)
|
||||
{
|
||||
l = (int)fread(tbuf, 1, 64, pFile);
|
||||
fclose(pFile);
|
||||
if (l > 0) RAND_add(tbuf, l, l);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Cleanup OpenSSL
|
||||
void __fastcall util_openssl_uninit()
|
||||
{
|
||||
--InitCounter;
|
||||
if (InitCounter > 0) { return; }
|
||||
|
||||
//RAND_cleanup(); // Does nothing.
|
||||
//CRYPTO_set_dynlock_create_callback(NULL); // Does nothing.
|
||||
//CRYPTO_set_dynlock_destroy_callback(NULL); // Does nothing.
|
||||
//CRYPTO_set_dynlock_lock_callback(NULL); // Does nothing.
|
||||
//CRYPTO_set_locking_callback(NULL); // Does nothing.
|
||||
//CRYPTO_set_id_callback(NULL); // Does nothing.
|
||||
CRYPTO_cleanup_all_ex_data();
|
||||
//sk_SSL_COMP_free(SSL_COMP_get_compression_methods()); // Does something, but it causes heap corruption...
|
||||
//CONF_modules_unload(1); // Does nothing.
|
||||
CONF_modules_free();
|
||||
EVP_cleanup();
|
||||
ERR_free_strings();
|
||||
//ERR_remove_state(0); // Deprecated in OpenSSL/1.1.x
|
||||
|
||||
OPENSSL_cleanup();
|
||||
}
|
||||
|
||||
// Add extension using V3 code: we can set the config file as NULL because we wont reference any other sections.
|
||||
int __fastcall util_add_ext(X509 *cert, int nid, char *value)
|
||||
{
|
||||
X509_EXTENSION *ex;
|
||||
X509V3_CTX ctx;
|
||||
// This sets the 'context' of the extensions. No configuration database
|
||||
X509V3_set_ctx_nodb(&ctx);
|
||||
// Issuer and subject certs: both the target since it is self signed, no request and no CRL
|
||||
X509V3_set_ctx(&ctx, cert, cert, NULL, NULL, 0);
|
||||
ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, value);
|
||||
if (!ex) return 0;
|
||||
|
||||
X509_add_ext(cert, ex, -1);
|
||||
X509_EXTENSION_free(ex);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void __fastcall util_freecert(struct util_cert* cert)
|
||||
{
|
||||
if (cert->x509 != NULL) X509_free(cert->x509);
|
||||
if (cert->pkey != NULL) EVP_PKEY_free(cert->pkey);
|
||||
cert->x509 = NULL;
|
||||
cert->pkey = NULL;
|
||||
}
|
||||
|
||||
int __fastcall util_to_cer(struct util_cert cert, char** data)
|
||||
{
|
||||
*data = NULL;
|
||||
return i2d_X509(cert.x509, (unsigned char**)data);
|
||||
}
|
||||
|
||||
int __fastcall util_from_cer(char* data, int datalen, struct util_cert* cert)
|
||||
{
|
||||
cert->pkey = NULL;
|
||||
cert->x509 = d2i_X509(NULL, (const unsigned char**)&data, datalen);
|
||||
return ((cert->x509) == NULL);
|
||||
}
|
||||
|
||||
int __fastcall util_from_pem_string(char *data, int datalen, struct util_cert* cert)
|
||||
{
|
||||
BIO* bio = BIO_new_mem_buf((void*)data, datalen);
|
||||
int retVal = 0;
|
||||
|
||||
if ((cert->pkey = PEM_read_bio_PrivateKey(bio, NULL, 0, NULL)) == NULL) { retVal = -1; }
|
||||
if ((cert->x509 = PEM_read_bio_X509(bio, NULL, 0, NULL)) == NULL) { retVal = -1; }
|
||||
|
||||
BIO_free(bio);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
int __fastcall util_from_pem(char* filename, struct util_cert* cert)
|
||||
{
|
||||
FILE *pFile = NULL;
|
||||
|
||||
if (filename == NULL) return -1;
|
||||
#ifdef WIN32
|
||||
fopen_s(&pFile, filename, "rbN");
|
||||
#else
|
||||
pFile = fopen(filename, "rb");
|
||||
#endif
|
||||
if (pFile == NULL) goto error;
|
||||
|
||||
if ((cert->pkey = PEM_read_PrivateKey(pFile, NULL, 0, NULL)) == NULL) goto error;
|
||||
if ((cert->x509 = PEM_read_X509(pFile, NULL, 0, NULL)) == NULL) goto error;
|
||||
|
||||
fclose(pFile);
|
||||
return 0;
|
||||
error:
|
||||
if (pFile != NULL) fclose(pFile);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int __fastcall util_to_p12(struct util_cert cert, char *password, char** data)
|
||||
{
|
||||
PKCS12 *p12;
|
||||
int len;
|
||||
p12 = PKCS12_create(password, "Certificate", cert.pkey, cert.x509, NULL, 0, 0, 0, 0, 0);
|
||||
*data = NULL;
|
||||
len = i2d_PKCS12(p12, (unsigned char**)data);
|
||||
PKCS12_free(p12);
|
||||
return len;
|
||||
}
|
||||
|
||||
int __fastcall util_from_p12(char* data, int datalen, char* password, struct util_cert* cert)
|
||||
{
|
||||
int r = 0;
|
||||
PKCS12 *p12 = NULL;
|
||||
if (data == NULL || datalen == 0) return 0;
|
||||
cert->x509 = NULL;
|
||||
cert->pkey = NULL;
|
||||
p12 = d2i_PKCS12(&p12, (const unsigned char**)&data, datalen);
|
||||
r = PKCS12_parse(p12, password, &(cert->pkey), &(cert->x509), NULL);
|
||||
PKCS12_free(p12);
|
||||
return r;
|
||||
}
|
||||
void __fastcall util_printcert(struct util_cert cert)
|
||||
{
|
||||
if (cert.x509 == NULL) return;
|
||||
X509_print_fp(stdout, cert.x509);
|
||||
}
|
||||
|
||||
void __fastcall util_printcert_pk(struct util_cert cert)
|
||||
{
|
||||
if (cert.pkey == NULL) return;
|
||||
//RSA_print_fp(stdout, cert.pkey->pkey.rsa, 0);
|
||||
RSA_print_fp(stdout, EVP_PKEY_get1_RSA(cert.pkey), 0);
|
||||
}
|
||||
|
||||
// Creates a X509 certificate, if rootcert is NULL this creates a root (self-signed) certificate.
|
||||
// Is the name parameter is NULL, the hex value of the hash of the public key will be the subject name.
|
||||
int __fastcall util_mkCert(struct util_cert *rootcert, struct util_cert* cert, int bits, int days, char* name, enum CERTIFICATE_TYPES certtype, struct util_cert* initialcert)
|
||||
{
|
||||
X509 *x = NULL;
|
||||
X509_EXTENSION *ex = NULL;
|
||||
EVP_PKEY *pk = NULL;
|
||||
RSA *rsa = NULL;
|
||||
X509_NAME *cname = NULL;
|
||||
X509 **x509p = NULL;
|
||||
EVP_PKEY **pkeyp = NULL;
|
||||
int hashlen = UTIL_HASHSIZE;
|
||||
char hash[UTIL_HASHSIZE];
|
||||
char serial[8];
|
||||
char nameStr[(UTIL_HASHSIZE * 2) + 2];
|
||||
BIGNUM *oBigNbr;
|
||||
|
||||
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
|
||||
|
||||
if (initialcert != NULL)
|
||||
{
|
||||
pk = X509_get_pubkey(initialcert->x509);
|
||||
rsa = EVP_PKEY_get1_RSA(initialcert->pkey);
|
||||
if ((x = X509_new()) == NULL) goto err;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((pkeyp == NULL) || (*pkeyp == NULL)) { if ((pk = EVP_PKEY_new()) == NULL) return 0; }
|
||||
else pk = *pkeyp;
|
||||
if ((x509p == NULL) || (*x509p == NULL)) { if ((x = X509_new()) == NULL) goto err; }
|
||||
else x = *x509p;
|
||||
oBigNbr = BN_new();
|
||||
rsa = RSA_new();
|
||||
BN_set_word(oBigNbr, RSA_F4);
|
||||
if (RSA_generate_key_ex(rsa, bits, oBigNbr, NULL) == -1)
|
||||
{
|
||||
RSA_free(rsa);
|
||||
BN_free(oBigNbr);
|
||||
abort();
|
||||
}
|
||||
BN_free(oBigNbr);
|
||||
}
|
||||
|
||||
if (!EVP_PKEY_assign_RSA(pk, rsa))
|
||||
{
|
||||
RSA_free(rsa);
|
||||
abort();
|
||||
}
|
||||
rsa = NULL;
|
||||
|
||||
util_randomtext(8, serial);
|
||||
X509_set_version(x, 2);
|
||||
ASN1_STRING_set(X509_get_serialNumber(x), serial, 8);
|
||||
X509_gmtime_adj(X509_get_notBefore(x), (long)60 * 60 * 24 * -10);
|
||||
X509_gmtime_adj(X509_get_notAfter(x), (long)60 * 60 * 24 * days);
|
||||
X509_set_pubkey(x, pk);
|
||||
|
||||
// Set the subject name
|
||||
cname = X509_get_subject_name(x);
|
||||
|
||||
if (name == NULL)
|
||||
{
|
||||
// Computer the hash of the public key
|
||||
//util_sha256((char*)x->cert_info->key->public_key->data, x->cert_info->key->public_key->length, hash); // OpenSSL 1.0
|
||||
X509_pubkey_digest(x, EVP_sha256(), (unsigned char*)hash, (unsigned int*)&hashlen); // OpenSSL 1.1
|
||||
|
||||
util_tohex(hash, UTIL_HASHSIZE, nameStr);
|
||||
X509_NAME_add_entry_by_txt(cname, "CN", MBSTRING_ASC, (unsigned char*)nameStr, -1, -1, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This function creates and adds the entry, working out the correct string type and performing checks on its length. Normally we'd check the return value for errors...
|
||||
X509_NAME_add_entry_by_txt(cname, "CN", MBSTRING_ASC, (unsigned char*)name, -1, -1, 0);
|
||||
}
|
||||
|
||||
if (rootcert == NULL)
|
||||
{
|
||||
// Its self signed so set the issuer name to be the same as the subject.
|
||||
X509_set_issuer_name(x, cname);
|
||||
|
||||
// Add various extensions: standard extensions
|
||||
util_add_ext(x, NID_basic_constraints, "critical,CA:TRUE");
|
||||
util_add_ext(x, NID_key_usage, "critical,keyCertSign,cRLSign");
|
||||
|
||||
util_add_ext(x, NID_subject_key_identifier, "hash");
|
||||
//util_add_ext(x, NID_netscape_cert_type, "sslCA");
|
||||
//util_add_ext(x, NID_netscape_comment, "example comment extension");
|
||||
|
||||
if (!X509_sign(x, pk, EVP_sha256())) goto err;
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is a sub-certificate
|
||||
cname = X509_get_subject_name(rootcert->x509);
|
||||
X509_set_issuer_name(x, cname);
|
||||
|
||||
// Add usual cert stuff
|
||||
ex = X509V3_EXT_conf_nid(NULL, NULL, NID_key_usage, "digitalSignature, keyEncipherment, keyAgreement");
|
||||
X509_add_ext(x, ex, -1);
|
||||
X509_EXTENSION_free(ex);
|
||||
|
||||
// Add usages: TLS server, TLS client, Intel(R) AMT Console
|
||||
//ex = X509V3_EXT_conf_nid(NULL, NULL, NID_ext_key_usage, "TLS Web Server Authentication, TLS Web Client Authentication, 2.16.840.1.113741.1.2.1, 2.16.840.1.113741.1.2.2");
|
||||
if (certtype == CERTIFICATE_TLS_SERVER)
|
||||
{
|
||||
// TLS server
|
||||
ex = X509V3_EXT_conf_nid(NULL, NULL, NID_ext_key_usage, "TLS Web Server Authentication");
|
||||
X509_add_ext(x, ex, -1);
|
||||
X509_EXTENSION_free(ex);
|
||||
}
|
||||
else if (certtype == CERTIFICATE_TLS_CLIENT)
|
||||
{
|
||||
// TLS client
|
||||
ex = X509V3_EXT_conf_nid(NULL, NULL, NID_ext_key_usage, "TLS Web Client Authentication");
|
||||
X509_add_ext(x, ex, -1);
|
||||
X509_EXTENSION_free(ex);
|
||||
}
|
||||
|
||||
if (!X509_sign(x, rootcert->pkey, EVP_sha256())) goto err;
|
||||
}
|
||||
|
||||
cert->x509 = x;
|
||||
cert->pkey = pk;
|
||||
|
||||
return 1;
|
||||
err:
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int __fastcall util_keyhash(struct util_cert cert, char* result)
|
||||
{
|
||||
int hashlen = UTIL_HASHSIZE;
|
||||
if (cert.x509 == NULL) return -1;
|
||||
//util_sha256((char*)(cert.x509->cert_info->key->public_key->data), cert.x509->cert_info->key->public_key->length, result); // OpenSSL 1.0
|
||||
X509_pubkey_digest(cert.x509, EVP_sha256(), (unsigned char*)result,(unsigned int *) &hashlen); // OpenSSL 1.1
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __fastcall util_keyhash2(X509* cert, char* result)
|
||||
{
|
||||
int hashlen = UTIL_HASHSIZE;
|
||||
if (cert == NULL) return -1;
|
||||
//util_sha256((char*)(cert->cert_info->key->public_key->data), cert->cert_info->key->public_key->length, result); // OpenSSL 1.0
|
||||
X509_pubkey_digest(cert, EVP_sha256(), (unsigned char*)result, (unsigned int*)&hashlen); // OpenSSL 1.1
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Sign this block of data, the first 32 bytes of the block must be avaialble to add the certificate hash.
|
||||
int __fastcall util_sign(struct util_cert cert, char* data, int datalen, char** signature)
|
||||
{
|
||||
int size = 0;
|
||||
unsigned int hashsize = UTIL_HASHSIZE;
|
||||
BIO *in = NULL;
|
||||
PKCS7 *message = NULL;
|
||||
*signature = NULL;
|
||||
if (datalen <= UTIL_HASHSIZE) return 0;
|
||||
|
||||
// Add hash of the certificate to start of data
|
||||
X509_digest(cert.x509, EVP_sha256(), (unsigned char*)data, &hashsize);
|
||||
|
||||
// Sign the block
|
||||
in = BIO_new_mem_buf(data, datalen);
|
||||
message = PKCS7_sign(cert.x509, cert.pkey, NULL, in, PKCS7_BINARY);
|
||||
if (message == NULL) goto error;
|
||||
size = i2d_PKCS7(message, (unsigned char**)signature);
|
||||
|
||||
error:
|
||||
if (message != NULL) PKCS7_free(message);
|
||||
if (in != NULL) BIO_free(in);
|
||||
return size;
|
||||
}
|
||||
|
||||
// Verify the signed block, the first 32 bytes of the data must be the certificate hash to work.
|
||||
int __fastcall util_verify(char* signature, int signlen, struct util_cert* cert, char** data)
|
||||
{
|
||||
unsigned int size, r;
|
||||
BIO *out = NULL;
|
||||
PKCS7 *message = NULL;
|
||||
char* data2 = NULL;
|
||||
char hash[UTIL_HASHSIZE];
|
||||
STACK_OF(X509) *st = NULL;
|
||||
|
||||
cert->x509 = NULL;
|
||||
cert->pkey = NULL;
|
||||
*data = NULL;
|
||||
message = d2i_PKCS7(NULL, (const unsigned char**)&signature, signlen);
|
||||
if (message == NULL) goto error;
|
||||
out = BIO_new(BIO_s_mem());
|
||||
|
||||
// Lets rebuild the original message and check the size
|
||||
size = i2d_PKCS7(message, NULL);
|
||||
if (size < (unsigned int)signlen) goto error;
|
||||
|
||||
// Check the PKCS7 signature, but not the certificate chain.
|
||||
r = PKCS7_verify(message, NULL, NULL, NULL, out, PKCS7_NOVERIFY);
|
||||
if (r == 0) goto error;
|
||||
|
||||
// If data block contains less than 32 bytes, fail.
|
||||
size = (unsigned int)BIO_get_mem_data(out, &data2);
|
||||
if (size <= UTIL_HASHSIZE) goto error;
|
||||
|
||||
// Copy the data block
|
||||
*data = (char*)malloc(size + 1);
|
||||
if (*data == NULL) goto error;
|
||||
memcpy_s(*data, size + 1, data2, size);
|
||||
(*data)[size] = 0;
|
||||
|
||||
// Get the certificate signer
|
||||
st = PKCS7_get0_signers(message, NULL, PKCS7_NOVERIFY);
|
||||
cert->x509 = X509_dup(sk_X509_value(st, 0));
|
||||
sk_X509_free(st);
|
||||
|
||||
// Get a full certificate hash of the signer
|
||||
r = UTIL_HASHSIZE;
|
||||
X509_digest(cert->x509, EVP_sha256(), (unsigned char*)hash, &r);
|
||||
|
||||
// Check certificate hash with first 32 bytes of data.
|
||||
if (memcmp(hash, *data, UTIL_HASHSIZE) != 0) goto error;
|
||||
|
||||
// Approved, cleanup and return.
|
||||
BIO_free(out);
|
||||
PKCS7_free(message);
|
||||
|
||||
return size;
|
||||
|
||||
error:
|
||||
if (out != NULL) BIO_free(out);
|
||||
if (message != NULL) PKCS7_free(message);
|
||||
if (*data != NULL) free(*data);
|
||||
if (cert->x509 != NULL) { X509_free(cert->x509); cert->x509 = NULL; }
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Encrypt a block of data for a target certificate
|
||||
int __fastcall util_encrypt(struct util_cert cert, char* data, int datalen, char** encdata)
|
||||
{
|
||||
int size = 0;
|
||||
BIO *in = NULL;
|
||||
PKCS7 *message = NULL;
|
||||
STACK_OF(X509) *encerts = NULL;
|
||||
*encdata = NULL;
|
||||
if (datalen == 0) return 0;
|
||||
|
||||
// Setup certificates
|
||||
encerts = sk_X509_new_null();
|
||||
sk_X509_push(encerts, cert.x509);
|
||||
|
||||
// Encrypt the block
|
||||
*encdata = NULL;
|
||||
in = BIO_new_mem_buf(data, datalen);
|
||||
message = PKCS7_encrypt(encerts, in, EVP_aes_128_cbc(), PKCS7_BINARY);
|
||||
if (message == NULL) return 0;
|
||||
size = i2d_PKCS7(message, (unsigned char**)encdata);
|
||||
BIO_free(in);
|
||||
PKCS7_free(message);
|
||||
sk_X509_free(encerts);
|
||||
return size;
|
||||
}
|
||||
|
||||
// Encrypt a block of data using multiple target certificates
|
||||
int __fastcall util_encrypt2(STACK_OF(X509) *certs, char* data, int datalen, char** encdata)
|
||||
{
|
||||
int size = 0;
|
||||
BIO *in = NULL;
|
||||
PKCS7 *message = NULL;
|
||||
*encdata = NULL;
|
||||
if (datalen == 0) return 0;
|
||||
|
||||
// Encrypt the block
|
||||
*encdata = NULL;
|
||||
in = BIO_new_mem_buf(data, datalen);
|
||||
message = PKCS7_encrypt(certs, in, EVP_aes_128_cbc(), PKCS7_BINARY);
|
||||
if (message == NULL) return 0;
|
||||
size = i2d_PKCS7(message, (unsigned char**)encdata);
|
||||
BIO_free(in);
|
||||
PKCS7_free(message);
|
||||
return size;
|
||||
}
|
||||
|
||||
// Decrypt a block of data using the specified certificate. The certificate must have a private key.
|
||||
int __fastcall util_decrypt(char* encdata, int encdatalen, struct util_cert cert, char** data)
|
||||
{
|
||||
unsigned int size, r;
|
||||
BIO *out = NULL;
|
||||
PKCS7 *message = NULL;
|
||||
char* data2 = NULL;
|
||||
|
||||
*data = NULL;
|
||||
if (cert.pkey == NULL) return 0;
|
||||
|
||||
message = d2i_PKCS7(NULL, (const unsigned char**)&encdata, encdatalen);
|
||||
if (message == NULL) goto error;
|
||||
out = BIO_new(BIO_s_mem());
|
||||
|
||||
// Lets rebuild the original message and check the size
|
||||
size = i2d_PKCS7(message, NULL);
|
||||
if (size < (unsigned int)encdatalen) goto error;
|
||||
|
||||
// Decrypt the PKCS7
|
||||
r = PKCS7_decrypt(message, cert.pkey, cert.x509, out, 0);
|
||||
if (r == 0) goto error;
|
||||
|
||||
// If data block contains 0 bytes, fail.
|
||||
size = (unsigned int)BIO_get_mem_data(out, &data2);
|
||||
if (size == 0) goto error;
|
||||
|
||||
// Copy the data block
|
||||
*data = (char*)malloc(size + 1);
|
||||
if (*data == NULL) goto error;
|
||||
memcpy_s(*data, size + 1, data2, size);
|
||||
(*data)[size] = 0;
|
||||
|
||||
// Cleanup and return.
|
||||
BIO_free(out);
|
||||
PKCS7_free(message);
|
||||
|
||||
return size;
|
||||
|
||||
error:
|
||||
if (out != NULL) BIO_free(out);
|
||||
if (message != NULL) PKCS7_free(message);
|
||||
if (*data != NULL) free(*data);
|
||||
if (data2 != NULL) free(data2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Encrypt a block of data using raw RSA. This is used to handle data in the most compact possible way.
|
||||
int __fastcall util_rsaencrypt(X509 *cert, char* data, int datalen, char** encdata)
|
||||
{
|
||||
int len;
|
||||
RSA *rsa;
|
||||
EVP_PKEY *pkey;
|
||||
|
||||
pkey = X509_get_pubkey(cert);
|
||||
rsa = EVP_PKEY_get1_RSA(pkey);
|
||||
if (datalen > RSA_size(rsa)) { EVP_PKEY_free(pkey); RSA_free(rsa); return 0; }
|
||||
*encdata = (char*)malloc(RSA_size(rsa));
|
||||
len = RSA_public_encrypt(datalen, (const unsigned char*)data, (unsigned char*)*encdata, rsa, RSA_PKCS1_OAEP_PADDING);
|
||||
EVP_PKEY_free(pkey);
|
||||
RSA_free(rsa);
|
||||
if (len == RSA_size(rsa)) return len;
|
||||
free(*encdata);
|
||||
*encdata = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Decrypt a block of data using raw RSA. This is used to handle data in the most compact possible way.
|
||||
int __fastcall util_rsadecrypt(struct util_cert cert, char* data, int datalen, char** decdata)
|
||||
{
|
||||
int len;
|
||||
RSA *rsa;
|
||||
|
||||
rsa = EVP_PKEY_get1_RSA(cert.pkey);
|
||||
*decdata = (char*)malloc(RSA_size(rsa));
|
||||
len = RSA_private_decrypt(datalen, (const unsigned char*)data, (unsigned char*)*decdata, rsa, RSA_PKCS1_OAEP_PADDING);
|
||||
RSA_free(rsa);
|
||||
if (len != 0) return len;
|
||||
free(*decdata);
|
||||
*decdata = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Verify the RSA signature of a block using SHA1 hash
|
||||
int __fastcall util_rsaverify(X509 *cert, char* data, int datalen, char* sign, int signlen)
|
||||
{
|
||||
int r;
|
||||
RSA *rsa = NULL;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
SHA_CTX c;
|
||||
char hash[20];
|
||||
|
||||
SHA1_Init(&c);
|
||||
SHA1_Update(&c, data, datalen);
|
||||
SHA1_Final((unsigned char*)hash, &c);
|
||||
pkey = X509_get_pubkey(cert);
|
||||
rsa = EVP_PKEY_get1_RSA(pkey);
|
||||
//rsa->pad = RSA_PKCS1_PADDING; // OPENSSL 1.0
|
||||
#ifdef WIN32
|
||||
r = RSA_verify(NID_sha1, (const unsigned char*)hash, 20, (const unsigned char*)sign, signlen, rsa);
|
||||
#else
|
||||
r = RSA_verify(NID_sha1, (const unsigned char*)hash, 20, (unsigned char*)sign, signlen, rsa);
|
||||
#endif
|
||||
EVP_PKEY_free(pkey);
|
||||
RSA_free(rsa);
|
||||
return r;
|
||||
}
|
||||
|
||||
#endif
|
||||
122
microstack/ILibCrypto.h
Normal file
122
microstack/ILibCrypto.h
Normal file
@@ -0,0 +1,122 @@
|
||||
#ifndef __ILIB_CRYPTO__
|
||||
#define __ILIB_CRYPTO__
|
||||
|
||||
#include "ILibParsers.h"
|
||||
|
||||
#if !defined(WIN32)
|
||||
#define __fastcall
|
||||
#endif
|
||||
|
||||
void __fastcall util_md5(char* data, int datalen, char* result);
|
||||
void __fastcall util_md5hex(char* data, int datalen, char *out);
|
||||
void __fastcall util_sha1(char* data, int datalen, char* result);
|
||||
char* __fastcall util_tohex(char* data, int len, char* out);
|
||||
char* __fastcall util_tohex2(char* data, int len, char* out);
|
||||
char* __fastcall util_tohex_lower(char* data, int len, char* out);
|
||||
int __fastcall util_hexToint(char *hexString, int hexStringLength);
|
||||
int __fastcall util_hexToBuf(char *hexString, int hexStringLength, char* output);
|
||||
|
||||
void __fastcall util_sha256(char* data, int datalen, char* result);
|
||||
int __fastcall util_sha256file(char* filename, char* result);
|
||||
|
||||
// File and data methods
|
||||
size_t __fastcall util_writefile(char* filename, char* data, int datalen);
|
||||
size_t __fastcall util_appendfile(char* filename, char* data, int datalen);
|
||||
size_t __fastcall util_readfile(char* filename, char** data, size_t maxlen);
|
||||
int __fastcall util_deletefile(char* filename);
|
||||
|
||||
#ifdef WIN32
|
||||
int __fastcall util_crc(unsigned char *buffer, int len, int initial_value);
|
||||
BOOL util_MoveFile(_In_ LPCSTR lpExistingFileName, _In_ LPCSTR lpNewFileName);
|
||||
BOOL util_CopyFile(_In_ LPCSTR lpExistingFileName, _In_ LPCSTR lpNewFileName, _In_ BOOL bFailIfExists);
|
||||
#endif
|
||||
|
||||
void __fastcall util_random(int length, char* result);
|
||||
void __fastcall util_randomtext(int length, char* result);
|
||||
|
||||
#define UTIL_HASHSIZE 32
|
||||
#define NONCE_SIZE 32
|
||||
#define HALF_NONCE_SIZE 16
|
||||
|
||||
#ifdef MICROSTACK_NOTLS
|
||||
#include "md5.h"
|
||||
#include "sha1.h"
|
||||
#include "microstack/SHA256.h"
|
||||
|
||||
#define SHA256_CTX struct sha256_ctx
|
||||
#define SHA256_Init(ctx) __sha256_init_ctx(ctx)
|
||||
#define SHA256_Update(ctx, data, len) __sha256_process_bytes(data, len, ctx)
|
||||
#define SHA256_Final(md, ctx) __sha256_finish_ctx(ctx, md)
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef MICROSTACK_NOTLS
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/md5.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
// Certificate structure
|
||||
typedef struct util_cert
|
||||
{
|
||||
X509 *x509;
|
||||
EVP_PKEY *pkey;
|
||||
}util_cert;
|
||||
typedef enum CERTIFICATE_TYPES
|
||||
{
|
||||
CERTIFICATE_ROOT = 1,
|
||||
CERTIFICATE_TLS_SERVER = 2,
|
||||
CERTIFICATE_TLS_CLIENT = 3
|
||||
}CERTIFICATE_TYPES;
|
||||
|
||||
|
||||
void __fastcall util_openssl_init();
|
||||
void __fastcall util_openssl_uninit();
|
||||
void __fastcall util_free(char* ptr);
|
||||
|
||||
// Certificate & crypto methods
|
||||
void __fastcall util_freecert(struct util_cert* cert);
|
||||
int __fastcall util_to_p12(struct util_cert cert, char *password, char** data);
|
||||
int __fastcall util_from_p12(char* data, int datalen, char* password, struct util_cert* cert);
|
||||
int __fastcall util_to_cer(struct util_cert cert, char** data);
|
||||
int __fastcall util_from_cer(char* data, int datalen, struct util_cert* cert);
|
||||
int __fastcall util_from_pem(char* filename, struct util_cert* cert);
|
||||
int __fastcall util_from_pem_string(char *data, int datalen, struct util_cert* cert);
|
||||
int __fastcall util_mkCert(struct util_cert *rootcert, struct util_cert* cert, int bits, int days, char* name, enum CERTIFICATE_TYPES certtype, struct util_cert* initialcert);
|
||||
void __fastcall util_printcert(struct util_cert cert);
|
||||
void __fastcall util_printcert_pk(struct util_cert cert);
|
||||
|
||||
int __fastcall util_keyhash(struct util_cert cert, char* result);
|
||||
int __fastcall util_keyhash2(X509* cert, char* result);
|
||||
int __fastcall util_sign(struct util_cert cert, char* data, int datalen, char** signature);
|
||||
int __fastcall util_verify(char* signature, int signlen, struct util_cert* cert, char** data);
|
||||
int __fastcall util_encrypt(struct util_cert cert, char* data, int datalen, char** encdata);
|
||||
int __fastcall util_encrypt2(STACK_OF(X509) *certs, char* data, int datalen, char** encdata);
|
||||
int __fastcall util_decrypt(char* encdata, int encdatalen, struct util_cert cert, char** data);
|
||||
|
||||
int __fastcall util_rsaencrypt(X509 *cert, char* data, int datalen, char** encdata);
|
||||
int __fastcall util_rsadecrypt(struct util_cert cert, char* data, int datalen, char** decdata);
|
||||
int __fastcall util_rsaverify(X509 *cert, char* data, int datalen, char* sign, int signlen);
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_DEBUG)
|
||||
|
||||
// Display only
|
||||
#ifdef ANDROID
|
||||
#include <android/log.h>
|
||||
#define MSG(...) __android_log_print(ANDROID_LOG_DEBUG, "MeshAgent", __VA_ARGS__);
|
||||
#elif NACL
|
||||
#include "chrome/nacl.h"
|
||||
#define MSG(...) ni_log(__VA_ARGS__);
|
||||
#else
|
||||
#define MSG(...) printf(__VA_ARGS__);fflush(NULL)
|
||||
#endif
|
||||
#define DEBUGSTATEMENT(x) x
|
||||
#else
|
||||
#ifndef MSG
|
||||
#define MSG(...)
|
||||
#endif
|
||||
#define DEBUGSTATEMENT(x)
|
||||
#endif
|
||||
#endif
|
||||
136
microstack/ILibIPAddressMonitor.c
Normal file
136
microstack/ILibIPAddressMonitor.c
Normal file
@@ -0,0 +1,136 @@
|
||||
#ifdef WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <iphlpapi.h>
|
||||
#include <Dbghelp.h>
|
||||
#endif
|
||||
#include "ILibParsers.h"
|
||||
|
||||
#ifdef _POSIX
|
||||
#include <netinet/in.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <net/if.h>
|
||||
#endif
|
||||
|
||||
typedef void* ILibIPAddressMonitor;
|
||||
typedef void(*ILibIPAddressMonitor_Handler)(ILibIPAddressMonitor sender, void *user);
|
||||
typedef struct _ILibIPAddressMonitor
|
||||
{
|
||||
ILibChain_Link chainLink;
|
||||
ILibIPAddressMonitor_Handler onUpdate;
|
||||
void *user;
|
||||
#ifdef WIN32
|
||||
SOCKET mSocket;
|
||||
DWORD bytesReturned;
|
||||
WSAOVERLAPPED reserved;
|
||||
#elif defined (_POSIX)
|
||||
int mSocket;
|
||||
struct sockaddr_nl addr;
|
||||
#endif
|
||||
|
||||
}_ILibIPAddressMonitor;
|
||||
int ILibMemory_IPAddressMonitor_CONTAINER_SIZE = sizeof(_ILibIPAddressMonitor);
|
||||
void ILibIPAddressMonitor_MicrostackThreadDispatch(void *chain, void *user);
|
||||
|
||||
#ifdef WIN32
|
||||
void CALLBACK ILibIPAddressMonitor_dispatch(
|
||||
IN DWORD dwError,
|
||||
IN DWORD cbTransferred,
|
||||
IN LPWSAOVERLAPPED lpOverlapped,
|
||||
IN DWORD dwFlags
|
||||
)
|
||||
{
|
||||
if (dwError == 0)
|
||||
{
|
||||
_ILibIPAddressMonitor *obj = (_ILibIPAddressMonitor*)lpOverlapped->hEvent;
|
||||
ILibChain_RunOnMicrostackThread(obj->chainLink.ParentChain, ILibIPAddressMonitor_MicrostackThreadDispatch, obj);
|
||||
}
|
||||
}
|
||||
void ILibIPAddressMonitor_MicrostackThreadDispatch(void *chain, void *user)
|
||||
{
|
||||
_ILibIPAddressMonitor *obj = (_ILibIPAddressMonitor*)user;
|
||||
if (obj->onUpdate != NULL) { obj->onUpdate(obj, obj->user); }
|
||||
WSAIoctl(obj->mSocket, SIO_ADDRESS_LIST_CHANGE, NULL, 0, NULL, 0, &(obj->bytesReturned), &(obj->reserved), ILibIPAddressMonitor_dispatch);
|
||||
}
|
||||
#endif
|
||||
|
||||
void ILibIPAddressMonitor_Destroy(void *object)
|
||||
{
|
||||
_ILibIPAddressMonitor *obj = (_ILibIPAddressMonitor*)object;
|
||||
|
||||
#ifdef WIN32
|
||||
closesocket(obj->mSocket);
|
||||
obj->mSocket = INVALID_SOCKET;
|
||||
#elif defined(_POSIX)
|
||||
close(obj->mSocket);
|
||||
obj->mSocket = -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(_POSIX)
|
||||
void ILibIPAddressMonitor_PreSelect(void* object, fd_set *readset, fd_set *writeset, fd_set *errorset, int* blocktime)
|
||||
{
|
||||
_ILibIPAddressMonitor *obj = (_ILibIPAddressMonitor*)object;
|
||||
FD_SET(obj->mSocket, readset);
|
||||
}
|
||||
void ILibIPAddressMonitor_PostSelect(void* object, int slct, fd_set *readset, fd_set *writeset, fd_set *errorset)
|
||||
{
|
||||
char buffer[4096];
|
||||
int len;
|
||||
int update = 0;
|
||||
struct nlmsghdr *nlh = (struct nlmsghdr *)buffer;
|
||||
|
||||
_ILibIPAddressMonitor *obj = (_ILibIPAddressMonitor*)object;
|
||||
if (FD_ISSET(obj->mSocket, readset) != 0)
|
||||
{
|
||||
while ((len = recv(obj->mSocket, nlh, sizeof(buffer), 0)) > 0)
|
||||
{
|
||||
while ((NLMSG_OK(nlh, len)) && (nlh->nlmsg_type != NLMSG_DONE))
|
||||
{
|
||||
if (nlh->nlmsg_type == RTM_NEWADDR || nlh->nlmsg_type == RTM_DELADDR)
|
||||
{
|
||||
update = 1;
|
||||
}
|
||||
nlh = NLMSG_NEXT(nlh, len);
|
||||
}
|
||||
}
|
||||
|
||||
if (update != 0 && obj->onUpdate != NULL) { obj->onUpdate(obj, obj->user); }
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
ILibIPAddressMonitor ILibIPAddressMonitor_Create(void *chain, ILibIPAddressMonitor_Handler handler, void *user)
|
||||
{
|
||||
_ILibIPAddressMonitor *obj = (_ILibIPAddressMonitor*)ILibChain_Link_Allocate(ILibMemory_IPAddressMonitor_CONTAINER_SIZE, 0);
|
||||
obj->onUpdate = handler;
|
||||
obj->user = user;
|
||||
#ifdef WIN32
|
||||
obj->reserved.hEvent = (HANDLE)obj;
|
||||
obj->mSocket = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
WSAIoctl(obj->mSocket, SIO_ADDRESS_LIST_CHANGE, NULL, 0, NULL, 0, &(obj->bytesReturned), &(obj->reserved), ILibIPAddressMonitor_dispatch);
|
||||
#elif defined (_POSIX)
|
||||
obj->mSocket = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
|
||||
int flags = fcntl(obj->mSocket, F_GETFL, 0);
|
||||
fcntl(obj->mSocket, F_SETFL, O_NONBLOCK | flags);
|
||||
|
||||
memset(&(obj->addr), 0, sizeof(obj->addr));
|
||||
obj->addr.nl_family = AF_NETLINK;
|
||||
obj->addr.nl_groups = RTMGRP_IPV4_IFADDR;
|
||||
|
||||
if (bind(obj->mSocket, (struct sockaddr *)&(obj->addr), sizeof(obj->addr)) == -1)
|
||||
{
|
||||
close(obj->mSocket);
|
||||
free(obj);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
obj->chainLink.PreSelectHandler = ILibIPAddressMonitor_PreSelect;
|
||||
obj->chainLink.PostSelectHandler = ILibIPAddressMonitor_PostSelect;
|
||||
#endif
|
||||
|
||||
obj->chainLink.DestroyHandler = ILibIPAddressMonitor_Destroy;
|
||||
ILibAddToChain(chain, obj);
|
||||
return((ILibIPAddressMonitor)obj);
|
||||
}
|
||||
11
microstack/ILibIPAddressMonitor.h
Normal file
11
microstack/ILibIPAddressMonitor.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#ifndef __ILIBIPADDRESSMONITOR__
|
||||
#define __ILIBIPADDRESSMONITOR__
|
||||
|
||||
typedef void* ILibIPAddressMonitor;
|
||||
typedef void(*ILibIPAddressMonitor_Handler)(ILibIPAddressMonitor sender, void *user);
|
||||
|
||||
|
||||
extern int ILibMemory_IPAddressMonitor_CONTAINER_SIZE;
|
||||
ILibIPAddressMonitor ILibIPAddressMonitor_Create(void *chain, ILibIPAddressMonitor_Handler handler, void *user);
|
||||
|
||||
#endif
|
||||
444
microstack/ILibMulticastSocket.c
Normal file
444
microstack/ILibMulticastSocket.c
Normal file
@@ -0,0 +1,444 @@
|
||||
/*
|
||||
Copyright 2006 - 2017 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(_MINCORE)
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include <crtdbg.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 "ILibAsyncUDPSocket.h"
|
||||
#include "ILibAsyncSocket.h"
|
||||
|
||||
#define INET_SOCKADDR_LENGTH(x) ((x==AF_INET6?sizeof(struct sockaddr_in6):sizeof(struct sockaddr_in)))
|
||||
#define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR, 12)
|
||||
|
||||
struct ILibMulticastSocket_StateModule
|
||||
{
|
||||
ILibChain_Link ChainLink;
|
||||
void *UDPServer;
|
||||
void *UDPServer6;
|
||||
void **UDPServers;
|
||||
void *User;
|
||||
void *Tag;
|
||||
int TTL;
|
||||
int Loopback;
|
||||
unsigned short LocalPort;
|
||||
ILibAsyncUDPSocket_OnData OnData;
|
||||
|
||||
// The IPv4 and IPv6 multicast addresses.
|
||||
struct sockaddr_in MulticastAddr;
|
||||
struct sockaddr_in6 MulticastAddr6;
|
||||
|
||||
// Lists of local IPv4 and IPv6 interfaces
|
||||
struct sockaddr_in *AddressListV4;
|
||||
int AddressListLengthV4;
|
||||
int* IndexListV6;
|
||||
int IndexListLenV6;
|
||||
|
||||
// Sockets used to sent and receive messages
|
||||
#if defined(WIN32) || defined(_WIN32_WCE)
|
||||
SOCKET NOTIFY_SEND_socks;
|
||||
SOCKET NOTIFY_SEND_socks6;
|
||||
#else
|
||||
int NOTIFY_SEND_socks;
|
||||
int NOTIFY_SEND_socks6;
|
||||
#endif
|
||||
};
|
||||
|
||||
// Received a UDP packet on the IPv4 socket, process it.
|
||||
void UDPSocket_OnDataV4(ILibAsyncUDPSocket_SocketModule socketModule, char* buffer, int bufferLength, struct sockaddr_in6 *remoteInterface, void *user, void *user2, int *PAUSE)
|
||||
{
|
||||
struct ILibMulticastSocket_StateModule* module = (struct ILibMulticastSocket_StateModule*)user;
|
||||
|
||||
// Call the user
|
||||
if (module->OnData != NULL) module->OnData(socketModule, buffer, bufferLength, remoteInterface, module->User, user2, PAUSE);
|
||||
}
|
||||
|
||||
// Received a UDP packet on the IPv6 socket, process it.
|
||||
void UDPSocket_OnDataV6(ILibAsyncUDPSocket_SocketModule socketModule, char* buffer, int bufferLength, struct sockaddr_in6 *remoteInterface, void *user, void *user2, int *PAUSE)
|
||||
{
|
||||
struct ILibMulticastSocket_StateModule* module = (struct ILibMulticastSocket_StateModule*)user;
|
||||
|
||||
// Remove any traffic from IPv4 mapped addresses because the IPv4 socket will take care of it.
|
||||
if (ILibIsIPv4MappedAddr((struct sockaddr*)remoteInterface)) return;
|
||||
|
||||
// Call the user
|
||||
if (module->OnData != NULL) module->OnData(socketModule, buffer, bufferLength, remoteInterface, module->User, user2, PAUSE);
|
||||
}
|
||||
|
||||
int ILibMulticastSocket_ResetMulticast(struct ILibMulticastSocket_StateModule *module, int cleanuponly)
|
||||
{
|
||||
int i;
|
||||
int change = 0;
|
||||
struct sockaddr_in any4;
|
||||
struct sockaddr_in6 any6;
|
||||
int tAddressListLengthV4 = 0;
|
||||
struct sockaddr_in* tAddressListV4 = NULL;
|
||||
int tIndexListLenV6 = 0;
|
||||
int* tIndexListV6 = NULL;
|
||||
SOCKET socket;
|
||||
#ifdef WINSOCK2
|
||||
DWORD dwBytesReturned = 0;
|
||||
BOOL bNewBehavior = FALSE;
|
||||
#endif
|
||||
|
||||
// If this is not just cleanup, lets check to see if this operation is really needed
|
||||
if (!cleanuponly)
|
||||
{
|
||||
tAddressListLengthV4 = ILibGetLocalIPv4AddressList(&tAddressListV4, 0);
|
||||
|
||||
// See if there are any changes in IPv4 interfaces
|
||||
if (tAddressListLengthV4 != module->AddressListLengthV4) change = 1;
|
||||
else if (tAddressListV4 == NULL && module->AddressListV4 != NULL) change = 1;
|
||||
else if (tAddressListV4 != NULL && module->AddressListV4 == NULL) change = 1;
|
||||
else if (tAddressListV4 != NULL && module->AddressListV4 != NULL && memcmp(tAddressListV4, module->AddressListV4, sizeof(struct sockaddr_in) * tAddressListLengthV4) != 0) change = 1;
|
||||
|
||||
if (module->UDPServer6 != NULL)
|
||||
{
|
||||
tIndexListLenV6 = ILibGetLocalIPv6IndexList(&tIndexListV6);
|
||||
|
||||
// See if there are any changes in IPv6 interfaces
|
||||
if (tIndexListLenV6 != module->IndexListLenV6) change = 1;
|
||||
else if (tIndexListV6 != NULL && module->IndexListV6 == NULL) change = 1;
|
||||
else if (tIndexListV6 == NULL && module->IndexListV6 != NULL) change = 1;
|
||||
else if (tIndexListV6 != NULL && module->IndexListV6 != NULL && memcmp(tIndexListV6, module->IndexListV6, sizeof(int) * tIndexListLenV6) != 0) change = 1;
|
||||
}
|
||||
|
||||
// If change is zero, this update is not needed.
|
||||
if (change == 0) { free(tAddressListV4); free(tIndexListV6); return 0; }
|
||||
}
|
||||
|
||||
// Free the address lists
|
||||
if (module->AddressListV4 != NULL) { free(module->AddressListV4); module->AddressListV4 = NULL; }
|
||||
if (module->IndexListV6 != NULL) { free(module->IndexListV6); module->IndexListV6 = NULL; }
|
||||
|
||||
// Free the IPv4 server sockets
|
||||
if (module->UDPServers != NULL)
|
||||
{
|
||||
for(i = 0; i < module->AddressListLengthV4; ++i) { if (module->UDPServers[i] != NULL) { ILibChain_SafeRemove(module->ChainLink.ParentChain, module->UDPServers[i]); } }
|
||||
free(module->UDPServers);
|
||||
module->UDPServers = NULL;
|
||||
}
|
||||
|
||||
// If we only want to cleanup, exit now
|
||||
if (cleanuponly) return 0;
|
||||
|
||||
// Setup Any4 address
|
||||
memset(&any4, 0, sizeof(struct sockaddr_in));
|
||||
any4.sin_family = AF_INET;
|
||||
any4.sin_port = htons(module->LocalPort);
|
||||
|
||||
// Setup Any6 address
|
||||
memset(&any6, 0, sizeof(struct sockaddr_in6));
|
||||
any6.sin6_family = AF_INET6;
|
||||
any6.sin6_port = htons(module->LocalPort);
|
||||
// Join the IPv4 multicast group
|
||||
if (tAddressListV4 != NULL && module->MulticastAddr.sin_family != 0)
|
||||
{
|
||||
// Get the list of local interfaces
|
||||
module->AddressListLengthV4 = tAddressListLengthV4;
|
||||
module->AddressListV4 = tAddressListV4;
|
||||
if (module->AddressListLengthV4 > 0 && module->AddressListV4 != NULL)
|
||||
{
|
||||
if ((module->UDPServers = (void**)malloc(sizeof(void*) * module->AddressListLengthV4)) == NULL) ILIBCRITICALEXIT(254);
|
||||
|
||||
// Join the same multicast group on all interfaces & create interface-specific sockets
|
||||
for(i = 0; i < module->AddressListLengthV4; ++i)
|
||||
{
|
||||
module->AddressListV4[i].sin_port = htons(module->LocalPort);
|
||||
module->UDPServers[i] = ILibAsyncUDPSocket_CreateEx(module->ChainLink.ParentChain, 0, (struct sockaddr*)&(module->AddressListV4[i]), ILibAsyncUDPSocket_Reuse_SHARED, UDPSocket_OnDataV4, NULL, module);
|
||||
if (module->UDPServers[i] != NULL)
|
||||
{
|
||||
ILibAsyncUDPSocket_JoinMulticastGroupV4(module->UDPServers[i], &(module->MulticastAddr), (struct sockaddr*)&(module->AddressListV4[i]));
|
||||
ILibAsyncUDPSocket_SetLocalInterface(module->UDPServers[i], (struct sockaddr*)&(module->AddressListV4[i]));
|
||||
socket = ILibAsyncUDPSocket_GetSocket(module->UDPServers[i]);
|
||||
#if !defined(NACL)
|
||||
if (setsockopt(socket, IPPROTO_IP, IP_MULTICAST_TTL, (const char*)&(module->TTL), sizeof(int)) != 0) ILIBCRITICALERREXIT(253);
|
||||
if (setsockopt(socket, IPPROTO_IP, IP_MULTICAST_LOOP, (const char*)&(module->Loopback), sizeof(int)) != 0) ILIBCRITICALERREXIT(253);
|
||||
if (setsockopt(socket, IPPROTO_IP, IP_MULTICAST_LOOP, (const char*)&(module->Loopback), sizeof(int)) != 0) ILIBCRITICALERREXIT(253);
|
||||
#endif
|
||||
module->AddressListV4[i].sin_port = 0;
|
||||
|
||||
// This will cause the socket not to stop if sending a packet to an invalid UDP port
|
||||
#ifdef WINSOCK2
|
||||
WSAIoctl(socket, SIO_UDP_CONNRESET, &bNewBehavior, sizeof(bNewBehavior), NULL, 0, &dwBytesReturned, NULL, NULL);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (tAddressListV4 != NULL) free(tAddressListV4);
|
||||
// Join the IPv6 multicast group
|
||||
if (tIndexListLenV6 != 0 && tIndexListV6 != NULL && module->MulticastAddr6.sin6_family != 0 && module->UDPServer6 != NULL)
|
||||
{
|
||||
// Get the list of local interfaces
|
||||
module->IndexListLenV6 = tIndexListLenV6;
|
||||
module->IndexListV6 = tIndexListV6;
|
||||
|
||||
// Join the same multicast group on all interfaces
|
||||
for(i = 0; i<module->IndexListLenV6; ++i) { ILibAsyncUDPSocket_JoinMulticastGroupV6(module->UDPServer6, &(module->MulticastAddr6), module->IndexListV6[i]); }
|
||||
}
|
||||
else if (tIndexListV6 != NULL) free(tIndexListV6);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
// Perform a local network broadcast of this packet
|
||||
void ILibMulticastSocket_BroadcastUdpPacketV4(struct ILibMulticastSocket_StateModule *module, struct sockaddr_in* addr, char* data, int datalen, int count, struct sockaddr *localif)
|
||||
{
|
||||
int i,j;
|
||||
SOCKET socket;
|
||||
//printf("IPv4 Broadcasting %d bytes.\r\n", datalen);
|
||||
|
||||
for(i = 0; i < module->AddressListLengthV4; ++i)
|
||||
{
|
||||
#ifdef WINSOCK2
|
||||
if (localif == NULL || ((struct sockaddr_in*)localif)->sin_addr.S_un.S_addr == module->AddressListV4[i].sin_addr.S_un.S_addr)
|
||||
#else
|
||||
if (localif == NULL || ((struct sockaddr_in*)localif)->sin_addr.s_addr == module->AddressListV4[i].sin_addr.s_addr)
|
||||
#endif
|
||||
{
|
||||
if (module->NOTIFY_SEND_socks != 0)
|
||||
{
|
||||
#if (!defined(_WIN32_WCE) || (defined(_WIN32_WCE) && _WIN32_WCE>=400)) && !defined(NACL)
|
||||
setsockopt(module->NOTIFY_SEND_socks, IPPROTO_IP, IP_MULTICAST_IF, (const char*)&(module->AddressListV4[i].sin_addr), sizeof(struct in_addr));
|
||||
for (j = 0; j < count; j++) sendto(module->NOTIFY_SEND_socks, data, datalen, 0, (struct sockaddr*)addr, sizeof(struct sockaddr_in));
|
||||
#else
|
||||
for (j = 0; j < count; j++) sendto(module->NOTIFY_SEND_socks, data, datalen, 0, (struct sockaddr*)addr, sizeof(struct sockaddr_in));
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if (!defined(_WIN32_WCE) || (defined(_WIN32_WCE) && _WIN32_WCE>=400)) && !defined(NACL)
|
||||
if (module->UDPServers[i] != NULL)
|
||||
{
|
||||
socket = ILibAsyncUDPSocket_GetSocket(module->UDPServers[i]);
|
||||
setsockopt(socket, IPPROTO_IP, IP_MULTICAST_IF, (const char*)&(module->AddressListV4[i].sin_addr), sizeof(struct in_addr));
|
||||
for (j = 0; j < count; j++) sendto(socket, data, datalen, 0, (struct sockaddr*)addr, sizeof(struct sockaddr_in));
|
||||
}
|
||||
#else
|
||||
for (j=0;j<count;j++) sendto(socket, data, datalen, 0, (struct sockaddr*)addr, sizeof(struct sockaddr_in));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
if (i == 0)
|
||||
{
|
||||
if (module->NOTIFY_SEND_socks != 0)
|
||||
{
|
||||
struct in_addr tmp;
|
||||
tmp.s_addr = addr->sin_addr.s_addr;
|
||||
addr->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
#if (!defined(_WIN32_WCE) || (defined(_WIN32_WCE) && _WIN32_WCE>=400)) && !defined(NACL)
|
||||
for (j = 0; j < count; j++) sendto(module->NOTIFY_SEND_socks, data, datalen, 0, (struct sockaddr*)addr, sizeof(struct sockaddr_in));
|
||||
#else
|
||||
for (j = 0; j < count; j++) sendto(module->NOTIFY_SEND_socks, data, datalen, 0, (struct sockaddr*)addr, sizeof(struct sockaddr_in));
|
||||
#endif
|
||||
addr->sin_addr.s_addr = tmp.s_addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Perform a local network broadcast of this packet
|
||||
void ILibMulticastSocket_BroadcastUdpPacketV6(struct ILibMulticastSocket_StateModule *module, struct sockaddr_in6* addr, char* data, int datalen, int count, struct sockaddr *localif)
|
||||
{
|
||||
int i,j;
|
||||
//printf("IPv6 Broadcasting %d bytes.\r\n", datalen);
|
||||
|
||||
// TODO: Consider the local interface
|
||||
UNREFERENCED_PARAMETER( localif );
|
||||
|
||||
if (module->NOTIFY_SEND_socks6 == 0) return;
|
||||
for(i = 0; i < module->IndexListLenV6; i++)
|
||||
{
|
||||
#if (!defined(_WIN32_WCE) || (defined(_WIN32_WCE) && _WIN32_WCE>=400)) && !defined(NACL)
|
||||
setsockopt(module->NOTIFY_SEND_socks6, IPPROTO_IPV6, IPV6_MULTICAST_IF, (const char*)&(module->IndexListV6[i]), 4);
|
||||
for (j=0;j<count;j++) sendto(module->NOTIFY_SEND_socks6, data, datalen, 0, (struct sockaddr*)addr, sizeof(struct sockaddr_in6));
|
||||
#else
|
||||
for (j=0;j<count;j++) sendto(module->NOTIFY_SEND_socks6, data, datalen, 0, (struct sockaddr*)addr, sizeof(struct sockaddr_in6));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// Perform network broadcast of this packet
|
||||
void ILibMulticastSocket_Broadcast(struct ILibMulticastSocket_StateModule *module, char* data, int datalen, int count)
|
||||
{
|
||||
// Broadcast on both IPv4 and IPv6, but lets use IPv6 first.
|
||||
if (module->MulticastAddr6.sin6_family != 0) ILibMulticastSocket_BroadcastUdpPacketV6(module, &(module->MulticastAddr6), data, datalen, count, NULL);
|
||||
if (module->MulticastAddr.sin_family != 0) ILibMulticastSocket_BroadcastUdpPacketV4(module, &(module->MulticastAddr), data, datalen, count, NULL);
|
||||
}
|
||||
|
||||
// Perform network broadcast of this packet on a specific local interface
|
||||
void ILibMulticastSocket_BroadcastIF(struct ILibMulticastSocket_StateModule *module, char* data, int datalen, int count, struct sockaddr *localif)
|
||||
{
|
||||
// Broadcast on both IPv4 and IPv6, but lets use IPv6 first.
|
||||
if ((localif == NULL || localif->sa_family == AF_INET6) && module->MulticastAddr6.sin6_family != 0) ILibMulticastSocket_BroadcastUdpPacketV6(module, &(module->MulticastAddr6), data, datalen, count, localif);
|
||||
if ((localif == NULL || localif->sa_family == AF_INET) && module->MulticastAddr.sin_family != 0) ILibMulticastSocket_BroadcastUdpPacketV4(module, &(module->MulticastAddr), data, datalen, count, localif);
|
||||
}
|
||||
|
||||
// Perform unicast transmit using this socket.
|
||||
int ILibMulticastSocket_Unicast(struct ILibMulticastSocket_StateModule *module, struct sockaddr* target, char* data, int datalen)
|
||||
{
|
||||
if (target->sa_family == AF_INET6) return sendto(module->NOTIFY_SEND_socks6, data, datalen, 0, target, INET_SOCKADDR_LENGTH(target->sa_family));
|
||||
if (target->sa_family == AF_INET) return sendto(module->NOTIFY_SEND_socks, data, datalen, 0, target, INET_SOCKADDR_LENGTH(target->sa_family));
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Private method called when the chain is destroyed, we want to do our cleanup here
|
||||
void ILibMulticastSocket_Destroy(void *object)
|
||||
{
|
||||
ILibMulticastSocket_ResetMulticast((struct ILibMulticastSocket_StateModule*)object, 1);
|
||||
}
|
||||
|
||||
// Create a new MulticastSocket module. This module handles all send and receive traffic for IPv4 and IPv6 on a given multicast group.
|
||||
struct ILibMulticastSocket_StateModule *ILibMulticastSocket_Create(void *Chain, int BufferSize, unsigned short LocalPort, struct sockaddr_in *MulticastAddr, struct sockaddr_in6 *MulticastAddr6, ILibAsyncUDPSocket_OnData OnData, void *user, int loopback)
|
||||
{
|
||||
int optval = 1;
|
||||
struct sockaddr_in addr4;
|
||||
struct sockaddr_in6 addr6;
|
||||
struct ILibMulticastSocket_StateModule* module;
|
||||
|
||||
UNREFERENCED_PARAMETER( BufferSize );
|
||||
|
||||
// Allocate the new socket state
|
||||
module = (struct ILibMulticastSocket_StateModule*)malloc(sizeof(struct ILibMulticastSocket_StateModule));
|
||||
if (module == NULL) { PRINTERROR(); return NULL; }
|
||||
memset(module, 0, sizeof(struct ILibMulticastSocket_StateModule));
|
||||
|
||||
// Setup local IPv4 binding address
|
||||
memset(&addr4, 0, sizeof(struct sockaddr_in));
|
||||
addr4.sin_family = AF_INET;
|
||||
addr4.sin_port = htons(LocalPort);
|
||||
|
||||
// Setup local IPv6 binding address
|
||||
memset(&addr6, 0, sizeof(struct sockaddr_in6));
|
||||
addr6.sin6_family = AF_INET6;
|
||||
addr6.sin6_port = htons(LocalPort);
|
||||
|
||||
// Setup the multicasting module
|
||||
module->ChainLink.DestroyHandler = &ILibMulticastSocket_Destroy;
|
||||
module->ChainLink.ParentChain = Chain;
|
||||
module->LocalPort = LocalPort;
|
||||
module->TTL = 4;
|
||||
module->Loopback = loopback;
|
||||
module->OnData = OnData;
|
||||
module->User = user;
|
||||
if (MulticastAddr != NULL)
|
||||
{
|
||||
// Setup the IPv4 multicast address
|
||||
memcpy(&(module->MulticastAddr), MulticastAddr, sizeof(struct sockaddr_in));
|
||||
if (module->MulticastAddr.sin_port == 0) module->MulticastAddr.sin_port = htons(LocalPort);
|
||||
|
||||
// Setup incoming IPv4 socket
|
||||
module->UDPServer = ILibAsyncUDPSocket_CreateEx(Chain, 0, (struct sockaddr*)&addr4, ILibAsyncUDPSocket_Reuse_SHARED, UDPSocket_OnDataV4, NULL, module);
|
||||
if (module->UDPServer == NULL) { free(module); PRINTERROR(); return NULL; }
|
||||
|
||||
// Set TTL, Reuse, Loop flags assumed to already be set
|
||||
module->NOTIFY_SEND_socks = ILibAsyncUDPSocket_GetSocket(module->UDPServer);
|
||||
#ifdef NACL
|
||||
|
||||
|
||||
#else
|
||||
if (setsockopt(module->NOTIFY_SEND_socks, IPPROTO_IP, IP_MULTICAST_TTL, (const char*)&(module->TTL), sizeof(int)) != 0) {ILIBCRITICALERREXIT(253);}
|
||||
if (setsockopt(module->NOTIFY_SEND_socks, IPPROTO_IP, IP_MULTICAST_LOOP, (const char*)&(module->Loopback), sizeof(int)) != 0) {ILIBCRITICALERREXIT(253);}
|
||||
|
||||
// Allow IPv4 Broadcast on this socket
|
||||
if (setsockopt(module->NOTIFY_SEND_socks, SOL_SOCKET, SO_BROADCAST, (char*)&optval, 4) != 0) ILIBCRITICALERREXIT(253);
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
if (MulticastAddr6 != NULL)
|
||||
{
|
||||
|
||||
// Setup incoming IPv6 socket
|
||||
module->UDPServer6 = ILibAsyncUDPSocket_CreateEx(Chain, 0, (struct sockaddr*)&addr6, ILibAsyncUDPSocket_Reuse_SHARED, UDPSocket_OnDataV6, NULL, module);
|
||||
if (module->UDPServer6 != NULL)
|
||||
{
|
||||
// Setup the IPv6 multicast address
|
||||
memcpy(&(module->MulticastAddr6), MulticastAddr6, sizeof(struct sockaddr_in6));
|
||||
if (module->MulticastAddr6.sin6_port == 0) module->MulticastAddr6.sin6_port = htons(LocalPort);
|
||||
|
||||
// Set TTL, IPv6, Loop and Reuse flags assumed to already be set
|
||||
module->NOTIFY_SEND_socks6 = ILibAsyncUDPSocket_GetSocket(module->UDPServer6);
|
||||
#ifdef NACL
|
||||
|
||||
#else
|
||||
if (setsockopt(module->NOTIFY_SEND_socks6, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (const char*)&(module->TTL), sizeof(int)) != 0) ILIBCRITICALERREXIT(253);
|
||||
if (setsockopt(module->NOTIFY_SEND_socks6, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (const char*)&(module->Loopback), sizeof(int)) != 0) ILIBCRITICALERREXIT(253);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined( NACL )
|
||||
ILibMulticastSocket_ResetMulticast(module, 0);
|
||||
#endif
|
||||
|
||||
ILibAddToChain(Chain, module);
|
||||
return module;
|
||||
}
|
||||
|
||||
void ILibSetTTL(void *vmodule, int ttl)
|
||||
{
|
||||
struct ILibMulticastSocket_StateModule* module = (struct ILibMulticastSocket_StateModule*)vmodule;
|
||||
module->TTL = ttl;
|
||||
#ifdef NACL
|
||||
|
||||
#else
|
||||
if (module->NOTIFY_SEND_socks != 0 && setsockopt(module->NOTIFY_SEND_socks, IPPROTO_IP, IP_MULTICAST_TTL, (const char*)&(module->TTL), sizeof(int)) != 0) ILIBCRITICALERREXIT(253);
|
||||
if (module->NOTIFY_SEND_socks6 != 0 && setsockopt(module->NOTIFY_SEND_socks6, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (const char*)&(module->TTL), sizeof(int)) != 0) ILIBCRITICALERREXIT(253);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ILibMulticastSocket_WakeOnLan(void *module, char* mac)
|
||||
{
|
||||
int i;
|
||||
struct sockaddr_in addr4;
|
||||
|
||||
// Create an IPv4 broadcast address
|
||||
memset(&addr4, 0, sizeof(struct sockaddr_in));
|
||||
addr4.sin_family = AF_INET;
|
||||
addr4.sin_port = htons(16990);
|
||||
#ifdef WINSOCK2
|
||||
addr4.sin_addr.S_un.S_addr = INADDR_BROADCAST; // Broadcast
|
||||
#else
|
||||
addr4.sin_addr.s_addr = INADDR_BROADCAST; // Broadcast
|
||||
#endif
|
||||
|
||||
// Create the magic packet
|
||||
memset(ILibScratchPad, 0xFF, 6);
|
||||
for (i = 1; i < 17; i++) memcpy(ILibScratchPad + (6 * i), mac, 6);
|
||||
|
||||
// Send it
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
// IPv4 Broadcast, works only in the same subnet
|
||||
sendto(((struct ILibMulticastSocket_StateModule*)module)->NOTIFY_SEND_socks, ILibScratchPad, 102, 0, (const struct sockaddr*)&addr4, sizeof(struct sockaddr_in));
|
||||
|
||||
// IPv4 & IPv6 Multicast. Only works if the machine still is subscribed to SSDP messages (S1 or S3 usualy), but has out-of-subnet range.
|
||||
ILibMulticastSocket_Broadcast((struct ILibMulticastSocket_StateModule*)module, ILibScratchPad, 102, 1);
|
||||
}
|
||||
}
|
||||
|
||||
42
microstack/ILibMulticastSocket.h
Normal file
42
microstack/ILibMulticastSocket.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
Copyright 2006 - 2017 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*! \file MulticastSocket.h
|
||||
\brief MicroStack APIs for UDP multicasting functionality
|
||||
*/
|
||||
|
||||
#ifndef __ILibMulticastSocket__
|
||||
#define __ILibMulticastSocket__
|
||||
#include "ILibAsyncSocket.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void *ILibMulticastSocket_Create(void *Chain, int BufferSize, unsigned short LocalPort, struct sockaddr_in *MulticastAddr, struct sockaddr_in6 *MulticastAddr6, ILibAsyncUDPSocket_OnData OnData, void *user, int loopback);
|
||||
int ILibMulticastSocket_Unicast(void *module, struct sockaddr* target, char* data, int datalen);
|
||||
void ILibMulticastSocket_BroadcastIF(void *module, char* data, int datalen, int count, struct sockaddr *localif);
|
||||
void ILibMulticastSocket_Broadcast(void *module, char* data, int datalen, int count);
|
||||
int ILibMulticastSocket_ResetMulticast(void *module, int cleanuponly);
|
||||
void ILibMulticastSocket_WakeOnLan(void *module, char* mac);
|
||||
void ILibSetTTL(void *module, int ttl);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
9084
microstack/ILibParsers.c
Normal file
9084
microstack/ILibParsers.c
Normal file
File diff suppressed because it is too large
Load Diff
1329
microstack/ILibParsers.h
Normal file
1329
microstack/ILibParsers.h
Normal file
File diff suppressed because it is too large
Load Diff
1373
microstack/ILibProcessPipe.c
Normal file
1373
microstack/ILibProcessPipe.c
Normal file
File diff suppressed because it is too large
Load Diff
96
microstack/ILibProcessPipe.h
Normal file
96
microstack/ILibProcessPipe.h
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
Copyright 2006 - 2017 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*! \file ILibNamedPipe.h
|
||||
\brief MicroStack APIs for various functions and tasks related to named pipes
|
||||
*/
|
||||
|
||||
#ifndef __ILibProcessPipe__
|
||||
#define __ILibProcessPipe__
|
||||
|
||||
#include "ILibParsers.h"
|
||||
|
||||
typedef void* ILibProcessPipe_Manager;
|
||||
typedef void* ILibProcessPipe_Process;
|
||||
typedef void(*ILibProcessPipe_Process_OutputHandler)(ILibProcessPipe_Process sender, char *buffer, int bufferLen, int* bytesConsumed, void* user);
|
||||
typedef void(*ILibProcessPipe_Process_SendOKHandler)(ILibProcessPipe_Process sender, void* user);
|
||||
typedef void(*ILibProcessPipe_Process_ExitHandler)(ILibProcessPipe_Process sender, int exitCode, void* user);
|
||||
|
||||
typedef void* ILibProcessPipe_Pipe;
|
||||
typedef void(*ILibProcessPipe_Pipe_ReadHandler)(ILibProcessPipe_Pipe sender, char *buffer, int bufferLen, int* bytesConsumed);
|
||||
typedef void(*ILibProcessPipe_Pipe_BrokenPipeHandler)(ILibProcessPipe_Pipe sender);
|
||||
|
||||
typedef enum ILibProcessPipe_SpawnTypes
|
||||
{
|
||||
ILibProcessPipe_SpawnTypes_DEFAULT = 0,
|
||||
ILibProcessPipe_SpawnTypes_USER = 1,
|
||||
ILibProcessPipe_SpawnTypes_WINLOGON = 2,
|
||||
ILibProcessPipe_SpawnTypes_TERM = 3,
|
||||
}ILibProcessPipe_SpawnTypes;
|
||||
|
||||
|
||||
extern const int ILibMemory_ILibProcessPipe_Pipe_CONTAINERSIZE;
|
||||
|
||||
#ifdef WIN32
|
||||
typedef enum ILibProcessPipe_Pipe_ReaderHandleType
|
||||
{
|
||||
ILibProcessPipe_Pipe_ReaderHandleType_NotOverLapped = 0, //!< Spawn a I/O processing thread
|
||||
ILibProcessPipe_Pipe_ReaderHandleType_Overlapped = 1 //!< Use Overlapped I/O
|
||||
}ILibProcessPipe_Pipe_ReaderHandleType;
|
||||
#endif
|
||||
|
||||
ILibTransport_DoneState ILibProcessPipe_Pipe_Write(ILibProcessPipe_Pipe writePipe, char* buffer, int bufferLen, ILibTransport_MemoryOwnership ownership);
|
||||
void ILibProcessPipe_Pipe_AddPipeReadHandler(ILibProcessPipe_Pipe targetPipe, int bufferSize, ILibProcessPipe_Pipe_ReadHandler OnReadHandler);
|
||||
#ifdef WIN32
|
||||
ILibProcessPipe_Pipe ILibProcessPipe_Pipe_CreateFromExistingWithExtraMemory(ILibProcessPipe_Manager manager, HANDLE existingPipe, ILibProcessPipe_Pipe_ReaderHandleType handleType, int extraMemorySize);
|
||||
#define ILibProcessPipe_Pipe_CreateFromExisting(PipeManager, ExistingPipe, HandleType) ILibProcessPipe_Pipe_CreateFromExistingWithExtraMemory(PipeManager, ExistingPipe, HandleType, 0)
|
||||
#else
|
||||
ILibProcessPipe_Pipe ILibProcessPipe_Pipe_CreateFromExistingWithExtraMemory(ILibProcessPipe_Manager manager, int existingPipe, int extraMemorySize);
|
||||
#define ILibProcessPipe_Pipe_CreateFromExisting(PipeManager, ExistingPipe) ILibProcessPipe_Pipe_CreateFromExistingWithExtraMemory(PipeManager, ExistingPipe, 0)
|
||||
#endif
|
||||
|
||||
void ILibProcessPipe_Pipe_SetBrokenPipeHandler(ILibProcessPipe_Pipe targetPipe, ILibProcessPipe_Pipe_BrokenPipeHandler handler);
|
||||
|
||||
ILibProcessPipe_Manager ILibProcessPipe_Manager_Create(void *chain);
|
||||
ILibProcessPipe_Process ILibProcessPipe_Manager_SpawnProcessEx2(ILibProcessPipe_Manager pipeManager, char* target, char* const * parameters, ILibProcessPipe_SpawnTypes spawnType, int extraMemorySize);
|
||||
#define ILibProcessPipe_Manager_SpawnProcess(pipeManager, target, parameters) ILibProcessPipe_Manager_SpawnProcessEx2(pipeManager, target, parameters, ILibProcessPipe_SpawnTypes_DEFAULT, 0)
|
||||
#define ILibProcessPipe_Manager_SpawnProcessEx(pipeManager, target, parameters, spawnType) ILibProcessPipe_Manager_SpawnProcessEx2(pipeManager, target, parameters, spawnType, 0)
|
||||
#define ILibProcessPipe_Manager_SpawnProcessWithExtraPipeMemory(pipeManager, target, parameters, memorySize) ILibProcessPipe_Manager_SpawnProcessEx2(pipeManager, target, parameters, ILibProcessPipe_SpawnTypes_DEFAULT, memorySize)
|
||||
void* ILibProcessPipe_Process_Kill(ILibProcessPipe_Process p);
|
||||
void* ILibProcessPipe_Process_KillEx(ILibProcessPipe_Process p);
|
||||
void ILibProcessPipe_Process_SoftKill(ILibProcessPipe_Process p);
|
||||
void ILibProcessPipe_Process_AddHandlers(ILibProcessPipe_Process module, int bufferSize, ILibProcessPipe_Process_ExitHandler exitHandler, ILibProcessPipe_Process_OutputHandler stdOut, ILibProcessPipe_Process_OutputHandler stdErr, ILibProcessPipe_Process_SendOKHandler sendOk, void *user);
|
||||
void ILibProcessPipe_Process_UpdateUserObject(ILibProcessPipe_Process module, void *userObj);
|
||||
ILibTransport_DoneState ILibProcessPipe_Process_WriteStdIn(ILibProcessPipe_Process p, char* buffer, int bufferLen, ILibTransport_MemoryOwnership ownership);
|
||||
void ILibProcessPipe_Pipe_Pause(ILibProcessPipe_Pipe pipeObject);
|
||||
void ILibProcessPipe_Pipe_Resume(ILibProcessPipe_Pipe pipeObject);
|
||||
void ILibProcessPipe_Pipe_SwapBuffers(ILibProcessPipe_Pipe pipeObject, char* newBuffer, int newBufferLen, int newBufferReadOffset, int newBufferTotalBytesRead, char **oldBuffer, int *oldBufferLen, int *oldBufferReadOffset, int *oldBufferTotalBytesRead);
|
||||
ILibProcessPipe_Pipe ILibProcessPipe_Process_GetStdErr(ILibProcessPipe_Process p);
|
||||
ILibProcessPipe_Pipe ILibProcessPipe_Process_GetStdOut(ILibProcessPipe_Process p);
|
||||
#ifdef WIN32
|
||||
DWORD ILibProcessPipe_Process_GetPID(ILibProcessPipe_Process p);
|
||||
#else
|
||||
pid_t ILibProcessPipe_Process_GetPID(ILibProcessPipe_Process p);
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
typedef BOOL(*ILibProcessPipe_WaitHandle_Handler)(HANDLE event, void* user);
|
||||
void ILibProcessPipe_WaitHandle_Add(ILibProcessPipe_Manager mgr, HANDLE event, void *user, ILibProcessPipe_WaitHandle_Handler callback);
|
||||
void ILibProcessPipe_WaitHandle_Remove(ILibProcessPipe_Manager mgr, HANDLE event);
|
||||
#endif
|
||||
#define ILibTransports_ProcessPipe 0x60
|
||||
#endif
|
||||
687
microstack/ILibRemoteLogging.c
Normal file
687
microstack/ILibRemoteLogging.c
Normal file
@@ -0,0 +1,687 @@
|
||||
/*
|
||||
Copyright 2006 - 2017 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(_MINCORE)
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include <crtdbg.h>
|
||||
#endif
|
||||
|
||||
#include "ILibRemoteLogging.h"
|
||||
#include "ILibParsers.h"
|
||||
#include "ILibWebServer.h"
|
||||
#include "ILibCrypto.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
char ILibScratchPad_RemoteLogging[255];
|
||||
//! Converts a sockaddr to a friendly string, using static memory, for logging purposes
|
||||
/*!
|
||||
\param addr sockaddr to convert
|
||||
\return friendly string representation (NULL Terminated)
|
||||
*/
|
||||
char* ILibRemoteLogging_ConvertAddress(struct sockaddr* addr)
|
||||
{
|
||||
ILibInet_ntop2((struct sockaddr*)addr, ILibScratchPad_RemoteLogging, sizeof(ILibScratchPad_RemoteLogging));
|
||||
return(ILibScratchPad_RemoteLogging);
|
||||
}
|
||||
|
||||
#ifdef _REMOTELOGGING
|
||||
|
||||
typedef struct ILibRemoteLogging_Session
|
||||
{
|
||||
unsigned int Flags;
|
||||
void* UserContext;
|
||||
}ILibRemoteLogging_Session;
|
||||
|
||||
typedef struct ILibRemoteLogging_Module
|
||||
{
|
||||
sem_t LogSyncLock;
|
||||
unsigned int LogFlags;
|
||||
|
||||
ILibRemoteLogging_OnWrite OutputSink;
|
||||
ILibRemoteLogging_OnRawForward RawForwardSink;
|
||||
int RawForwardOffset;
|
||||
ILibRemoteLogging_OnCommand CommandSink[15];
|
||||
ILibRemoteLogging_Session Sessions[5];
|
||||
}ILibRemoteLogging_Module;
|
||||
|
||||
void ILibRemoteLogging_Destroy(ILibRemoteLogging module)
|
||||
{
|
||||
ILibRemoteLogging_Module *obj = (ILibRemoteLogging_Module*)module;
|
||||
if (obj != NULL)
|
||||
{
|
||||
sem_destroy(&(obj->LogSyncLock));
|
||||
free(module);
|
||||
}
|
||||
}
|
||||
|
||||
void ILibRemoteLogging_CompactSessions(ILibRemoteLogging_Session sessions[], int sessionsLength)
|
||||
{
|
||||
int x=0,y=0;
|
||||
for(x=0;x<sessionsLength;++x)
|
||||
{
|
||||
if(sessions[x].UserContext == NULL)
|
||||
{
|
||||
for(y=x+1;y<sessionsLength;++y)
|
||||
{
|
||||
if(sessions[y].UserContext != NULL)
|
||||
{
|
||||
memcpy_s(&sessions[x], sizeof(ILibRemoteLogging_Session), &sessions[y], sizeof(ILibRemoteLogging_Session));
|
||||
memset(&sessions[y], 0, sizeof(ILibRemoteLogging_Session));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void ILibRemoteLogging_RemoveUserContext(ILibRemoteLogging_Session sessions[], int sessionsLength, void *userContext)
|
||||
{
|
||||
int i;
|
||||
for(i=0;i<sessionsLength;++i)
|
||||
{
|
||||
if(sessions[i].UserContext == NULL){break;}
|
||||
if(sessions[i].UserContext == userContext)
|
||||
{
|
||||
memset(&sessions[i], 0, sizeof(ILibRemoteLogging_Session));
|
||||
ILibRemoteLogging_CompactSessions(sessions, sessionsLength);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ILibRemoteLogging_Session* ILibRemoteLogging_GetSession(ILibRemoteLogging_Session sessions[], int sessionsLength, void *userContext)
|
||||
{
|
||||
int i;
|
||||
ILibRemoteLogging_Session *retVal = NULL;
|
||||
for(i=0;i<sessionsLength;++i)
|
||||
{
|
||||
if(sessions[i].UserContext == NULL)
|
||||
{
|
||||
sessions[i].Flags = 0x00;
|
||||
sessions[i].UserContext = userContext;
|
||||
retVal = &sessions[i];
|
||||
break;
|
||||
}
|
||||
else if(sessions[i].UserContext == userContext)
|
||||
{
|
||||
retVal = &sessions[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
void ILibRemoteLogging_LoggerCommand_Default(ILibRemoteLogging sender, ILibRemoteLogging_Modules module, unsigned short flags, char* data, int dataLen, void *userContext)
|
||||
{
|
||||
int len;
|
||||
char buf[72];
|
||||
|
||||
((unsigned short*)buf)[0] = htons((unsigned short)ILibRemoteLogging_Modules_Logger | (unsigned short)0x8000);
|
||||
((unsigned short*)buf)[1] = htons(ILibRemoteLogging_Flags_VerbosityLevel_1);
|
||||
|
||||
len = sprintf_s(buf + 4, sizeof(buf) - 4, "*** ILibRemoteLogging_FileTransport [No Logfile Set] ***");
|
||||
ILibTransport_Send(userContext, buf, len + 4, ILibTransport_MemoryOwnership_USER, ILibTransport_DoneState_COMPLETE);
|
||||
}
|
||||
void ILibRemoteLogging_SetRawForward(ILibRemoteLogging logger, int bufferOffset, ILibRemoteLogging_OnRawForward onRawForward)
|
||||
{
|
||||
((ILibRemoteLogging_Module*)logger)->RawForwardSink = onRawForward;
|
||||
((ILibRemoteLogging_Module*)logger)->RawForwardOffset = bufferOffset;
|
||||
}
|
||||
ILibRemoteLogging ILibRemoteLogging_Create(ILibRemoteLogging_OnWrite onOutput)
|
||||
{
|
||||
ILibRemoteLogging_Module *retVal;
|
||||
if((retVal = (ILibRemoteLogging_Module*)malloc(sizeof(ILibRemoteLogging_Module)))==NULL) {ILIBCRITICALEXIT(254);}
|
||||
memset(retVal, 0, sizeof(ILibRemoteLogging_Module));
|
||||
|
||||
sem_init(&(retVal->LogSyncLock), 0, 1);
|
||||
retVal->OutputSink = onOutput;
|
||||
|
||||
ILibRemoteLogging_RegisterCommandSink(retVal, ILibRemoteLogging_Modules_Logger, ILibRemoteLogging_LoggerCommand_Default);
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
void ILibRemoteLogging_RegisterCommandSink(ILibRemoteLogging logger, ILibRemoteLogging_Modules module, ILibRemoteLogging_OnCommand sink)
|
||||
{
|
||||
ILibRemoteLogging_Module *obj = (ILibRemoteLogging_Module*)logger;
|
||||
sem_wait(&(obj->LogSyncLock));
|
||||
obj->CommandSink[ILibWhichPowerOfTwo((int)module)] = sink;
|
||||
sem_post(&(obj->LogSyncLock));
|
||||
}
|
||||
|
||||
|
||||
void ILibRemoteLogging_DeleteUserContext(ILibRemoteLogging logger, void *userContext)
|
||||
{
|
||||
ILibRemoteLogging_Module *obj = (ILibRemoteLogging_Module*)logger;
|
||||
if (obj == NULL) { return; }
|
||||
|
||||
sem_wait(&(obj->LogSyncLock));
|
||||
ILibRemoteLogging_RemoveUserContext(obj->Sessions, sizeof(obj->Sessions) / sizeof(ILibRemoteLogging_Session), userContext);
|
||||
sem_post(&(obj->LogSyncLock));
|
||||
}
|
||||
|
||||
//! Converts binary data into a hex string, using static memory, for logging purposes
|
||||
/*!
|
||||
\param inVal Binary data to convert
|
||||
\param inValLength Binary data length
|
||||
\return hex string representation of binary data (NULL Terminated)
|
||||
*/
|
||||
char* ILibRemoteLogging_ConvertToHex(char* inVal, int inValLength)
|
||||
{
|
||||
util_tohex(inVal, inValLength<255?inValLength:254, ILibScratchPad_RemoteLogging);
|
||||
return(ILibScratchPad_RemoteLogging);
|
||||
}
|
||||
|
||||
void ILibRemoteLogging_SendCommand(ILibRemoteLogging loggingModule, ILibRemoteLogging_Modules module, ILibRemoteLogging_Flags flags, char *data, int dataLen, void *userContext)
|
||||
{
|
||||
ILibRemoteLogging_Module *obj = (ILibRemoteLogging_Module*)loggingModule;
|
||||
char dest[4096];
|
||||
|
||||
if(obj->OutputSink != NULL && ((dataLen + 4) < 4096))
|
||||
{
|
||||
((unsigned short*)dest)[0] = htons(module);
|
||||
((unsigned short*)dest)[1] = htons(flags);
|
||||
if(dataLen > 0) {memcpy_s(dest+4, sizeof(dest) - 4, data, dataLen);}
|
||||
obj->OutputSink(loggingModule, dest, 4+dataLen, userContext);
|
||||
}
|
||||
}
|
||||
//! Logging method using printf notation
|
||||
/*!
|
||||
\b NOTE: NO-OP if there is no connected viewers
|
||||
\param loggingModule ILibRemoteLogging Logging Module
|
||||
\param module ILibRemoteLogging_Modules Describing the source of the message
|
||||
\param flags ILibRemoteLogging_Flags Logging Flags
|
||||
\param format printf Format String
|
||||
\param ... Optional parameters
|
||||
*/
|
||||
void ILibRemoteLogging_printf(ILibRemoteLogging loggingModule, ILibRemoteLogging_Modules module, ILibRemoteLogging_Flags flags, char* format, ...)
|
||||
{
|
||||
int i;
|
||||
char dest[4096];
|
||||
int len;
|
||||
ILibRemoteLogging_Module *obj = (ILibRemoteLogging_Module*)loggingModule;
|
||||
|
||||
va_list argptr;
|
||||
|
||||
if (obj != NULL && obj->RawForwardSink != NULL)
|
||||
{
|
||||
// When Forwarding, TimeStamp will be added later
|
||||
len = obj->RawForwardOffset;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add TimeStamp to Log
|
||||
len = ILibGetLocalTime(dest + 4, (int)sizeof(dest) - 4);
|
||||
dest[len + 4] = ':';
|
||||
dest[len + 5] = ' ';
|
||||
len += 2;
|
||||
|
||||
len += 4; // Space for header (which isn't needed when forwarding)
|
||||
}
|
||||
|
||||
va_start(argptr, format);
|
||||
len += vsnprintf(dest+len, 4096 - len, format, argptr);
|
||||
va_end(argptr);
|
||||
|
||||
if (obj != NULL && obj->RawForwardSink != NULL)
|
||||
{
|
||||
obj->RawForwardSink(obj, module, flags, dest, len);
|
||||
}
|
||||
else if(obj != NULL && obj->OutputSink != NULL)
|
||||
{
|
||||
((unsigned short*)dest)[0] = htons((unsigned short)module | (unsigned short)0x8000);
|
||||
((unsigned short*)dest)[1] = htons(flags);
|
||||
|
||||
if ((module & ILibRemoteLogging_Modules_ConsolePrint) == ILibRemoteLogging_Modules_ConsolePrint) { printf("%s\n", dest + 4); }
|
||||
|
||||
sem_wait(&(obj->LogSyncLock));
|
||||
for(i=0;i<(sizeof(obj->Sessions)/sizeof(ILibRemoteLogging_Session)); ++i)
|
||||
{
|
||||
if(obj->Sessions[i].UserContext == NULL) {break;} // No more Sessions
|
||||
if((obj->Sessions[i].Flags & (unsigned int)module) == 0) {continue;} // Logging for this module is not enabled
|
||||
if(((obj->Sessions[i].Flags >> 16) & 0x3E) < (unsigned short)flags) {continue;} // Verbosity is not high enough
|
||||
sem_post(&(obj->LogSyncLock));
|
||||
obj->OutputSink(obj, dest, len, obj->Sessions[i].UserContext);
|
||||
sem_wait(&(obj->LogSyncLock));
|
||||
}
|
||||
sem_post(&(obj->LogSyncLock));
|
||||
}
|
||||
else if (obj == NULL && (module & ILibRemoteLogging_Modules_ConsolePrint) == ILibRemoteLogging_Modules_ConsolePrint)
|
||||
{
|
||||
printf("%s\n", dest + 4);
|
||||
}
|
||||
}
|
||||
void ILibRemoteLogging_Dispatch_Update(ILibRemoteLogging_Module *obj, unsigned short module, char* updateString, void *userContext)
|
||||
{
|
||||
char temp[255];
|
||||
int tempLen;
|
||||
|
||||
tempLen = ILibGetLocalTime((char*)temp, (int)sizeof(temp));
|
||||
temp[tempLen] = ':';
|
||||
temp[tempLen + 1] = ' ';
|
||||
tempLen += 2;
|
||||
|
||||
if((module & ILibRemoteLogging_Modules_WebRTC_STUN_ICE) == ILibRemoteLogging_Modules_WebRTC_STUN_ICE)
|
||||
{
|
||||
tempLen += sprintf_s(temp + tempLen, sizeof(temp) - tempLen, "WebRTC Module: STUN/ICE [%s]", updateString);
|
||||
ILibRemoteLogging_SendCommand(obj, (ILibRemoteLogging_Modules)(ILibRemoteLogging_Modules_WebRTC_STUN_ICE | 0x8000), ILibRemoteLogging_Flags_VerbosityLevel_1, temp, tempLen, userContext);
|
||||
}
|
||||
if((module & ILibRemoteLogging_Modules_WebRTC_DTLS) == ILibRemoteLogging_Modules_WebRTC_DTLS)
|
||||
{
|
||||
tempLen += sprintf_s(temp + tempLen, sizeof(temp) - tempLen, "WebRTC Module: DTLS [%s]", updateString);
|
||||
ILibRemoteLogging_SendCommand(obj, (ILibRemoteLogging_Modules)(ILibRemoteLogging_Modules_WebRTC_DTLS | 0x8000), ILibRemoteLogging_Flags_VerbosityLevel_1, temp, tempLen, userContext);
|
||||
}
|
||||
if((module & ILibRemoteLogging_Modules_WebRTC_SCTP) == ILibRemoteLogging_Modules_WebRTC_SCTP)
|
||||
{
|
||||
tempLen += sprintf_s(temp + tempLen, sizeof(temp) - tempLen, "WebRTC Module: SCTP [%s]", updateString);
|
||||
ILibRemoteLogging_SendCommand(obj, (ILibRemoteLogging_Modules)(ILibRemoteLogging_Modules_WebRTC_SCTP | 0x8000), ILibRemoteLogging_Flags_VerbosityLevel_1, temp, tempLen, userContext);
|
||||
}
|
||||
if ((module & ILibRemoteLogging_Modules_Agent_GuardPost) == ILibRemoteLogging_Modules_Agent_GuardPost)
|
||||
{
|
||||
tempLen += sprintf_s(temp + tempLen, sizeof(temp) - tempLen, "Agent Module: GuardPost [%s]", updateString);
|
||||
ILibRemoteLogging_SendCommand(obj, (ILibRemoteLogging_Modules)(ILibRemoteLogging_Modules_Agent_GuardPost | 0x8000), ILibRemoteLogging_Flags_VerbosityLevel_1, temp, tempLen, userContext);
|
||||
}
|
||||
if ((module & ILibRemoteLogging_Modules_Agent_P2P) == ILibRemoteLogging_Modules_Agent_P2P)
|
||||
{
|
||||
tempLen += sprintf_s(temp + tempLen, sizeof(temp) - tempLen, "Agent Module: Peer2Peer [%s]", updateString);
|
||||
ILibRemoteLogging_SendCommand(obj, (ILibRemoteLogging_Modules)(ILibRemoteLogging_Modules_Agent_P2P | 0x8000), ILibRemoteLogging_Flags_VerbosityLevel_1, temp, tempLen, userContext);
|
||||
}
|
||||
if ((module & ILibRemoteLogging_Modules_Microstack_AsyncSocket) == ILibRemoteLogging_Modules_Microstack_AsyncSocket)
|
||||
{
|
||||
tempLen += sprintf_s(temp + tempLen, sizeof(temp) - tempLen, "Microstack Module: AsyncSocket [%s]", updateString);
|
||||
ILibRemoteLogging_SendCommand(obj, (ILibRemoteLogging_Modules)(ILibRemoteLogging_Modules_Microstack_AsyncSocket | 0x8000), ILibRemoteLogging_Flags_VerbosityLevel_1, temp, tempLen, userContext);
|
||||
}
|
||||
if ((module & ILibRemoteLogging_Modules_Microstack_Web) == ILibRemoteLogging_Modules_Microstack_Web)
|
||||
{
|
||||
tempLen += sprintf_s(temp + tempLen, sizeof(temp) - tempLen, "Microstack Module: WebServer/Client [%s]", updateString);
|
||||
ILibRemoteLogging_SendCommand(obj, (ILibRemoteLogging_Modules)(ILibRemoteLogging_Modules_Microstack_Web | 0x8000), ILibRemoteLogging_Flags_VerbosityLevel_1, temp, tempLen, userContext);
|
||||
}
|
||||
if ((module & ILibRemoteLogging_Modules_Microstack_Generic) == ILibRemoteLogging_Modules_Microstack_Generic)
|
||||
{
|
||||
tempLen += sprintf_s(temp + tempLen, sizeof(temp) - tempLen, "Microstack Module: Generic [%s]", updateString);
|
||||
ILibRemoteLogging_SendCommand(obj, (ILibRemoteLogging_Modules)(ILibRemoteLogging_Modules_Microstack_Generic | 0x8000), ILibRemoteLogging_Flags_VerbosityLevel_1, temp, tempLen, userContext);
|
||||
}
|
||||
if ((module & ILibRemoteLogging_Modules_Agent_KVM) == ILibRemoteLogging_Modules_Agent_KVM)
|
||||
{
|
||||
tempLen += sprintf_s(temp + tempLen, sizeof(temp) - tempLen, "Agent Module: KVM [%s]", updateString);
|
||||
ILibRemoteLogging_SendCommand(obj, (ILibRemoteLogging_Modules)(ILibRemoteLogging_Modules_Agent_KVM | 0x8000), ILibRemoteLogging_Flags_VerbosityLevel_1, temp, tempLen, userContext);
|
||||
}
|
||||
if ((module & ILibRemoteLogging_Modules_Microstack_Pipe) == ILibRemoteLogging_Modules_Microstack_Pipe)
|
||||
{
|
||||
tempLen += sprintf_s(temp + tempLen, sizeof(temp) - tempLen, "Microstack Module: NamedPipe [%s]", updateString);
|
||||
ILibRemoteLogging_SendCommand(obj, (ILibRemoteLogging_Modules)(ILibRemoteLogging_Modules_Microstack_Pipe | 0x8000), ILibRemoteLogging_Flags_VerbosityLevel_1, temp, tempLen, userContext);
|
||||
}
|
||||
}
|
||||
int ILibRemoteLogging_IsModuleSet(ILibRemoteLogging loggingModule, ILibRemoteLogging_Modules module)
|
||||
{
|
||||
ILibRemoteLogging_Module *obj = (ILibRemoteLogging_Module*)loggingModule;
|
||||
int i;
|
||||
int retVal = 0;
|
||||
sem_wait(&(obj->LogSyncLock));
|
||||
for (i = 0; i < sizeof(obj->Sessions) / sizeof(ILibRemoteLogging_Session); ++i)
|
||||
{
|
||||
if (obj->Sessions[i].UserContext == NULL) { break; }
|
||||
if ((obj->Sessions[i].Flags & (unsigned int)module) == (unsigned int)module) { retVal = 1; break; }
|
||||
}
|
||||
sem_post(&(obj->LogSyncLock));
|
||||
return retVal;
|
||||
}
|
||||
void ILibRemoteLogging_Forward(ILibRemoteLogging loggingModule, char* data, int dataLen)
|
||||
{
|
||||
ILibRemoteLogging_Module *obj = (ILibRemoteLogging_Module*)loggingModule;
|
||||
int i;
|
||||
if (obj->OutputSink == NULL) { return; }
|
||||
|
||||
sem_wait(&(obj->LogSyncLock));
|
||||
for (i = 0; i < sizeof(obj->Sessions) / sizeof(ILibRemoteLogging_Session); ++i)
|
||||
{
|
||||
if (obj->Sessions[i].UserContext == NULL) { sem_post(&(obj->LogSyncLock)); return; }
|
||||
sem_post(&(obj->LogSyncLock));
|
||||
obj->OutputSink(obj, data, dataLen, obj->Sessions[i].UserContext);
|
||||
sem_wait(&(obj->LogSyncLock));
|
||||
}
|
||||
sem_post(&(obj->LogSyncLock));
|
||||
}
|
||||
int ILibRemoteLogging_Dispatch(ILibRemoteLogging loggingModule, char* data, int dataLen, void *userContext)
|
||||
{
|
||||
ILibRemoteLogging_Module *obj = (ILibRemoteLogging_Module*)loggingModule;
|
||||
unsigned short module;
|
||||
unsigned short flags;
|
||||
|
||||
ILibRemoteLogging_Session *session = NULL;
|
||||
|
||||
if(dataLen == 0 || userContext == NULL)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
module = ILibRemoteLogging_ReadModuleType(data);
|
||||
flags = ILibRemoteLogging_ReadFlags(data);
|
||||
|
||||
sem_wait(&(obj->LogSyncLock));
|
||||
session = ILibRemoteLogging_GetSession(obj->Sessions, sizeof(obj->Sessions) / sizeof(ILibRemoteLogging_Session), userContext);
|
||||
if(session == NULL) {sem_post(&(obj->LogSyncLock)); return 1;} // Too many users
|
||||
|
||||
if((flags & 0x3F) != 0x00)
|
||||
{
|
||||
// Change Verbosity of Logs
|
||||
if((flags & 0x01) == 0x01)
|
||||
{
|
||||
// Disable Modules
|
||||
session->Flags &= (0xFFFFFFFF ^ module);
|
||||
sem_post(&(obj->LogSyncLock));
|
||||
ILibRemoteLogging_Dispatch_Update(obj, module, "DISABLED", userContext);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// Enable Modules and Set Verbosity
|
||||
session->Flags &= 0xFFC0FFFF; // Reset Verbosity Flags
|
||||
session->Flags |= (flags << 16); // Set Verbosity Flags
|
||||
session->Flags |= (unsigned int)module; // Enable Modules
|
||||
sem_post(&(obj->LogSyncLock));
|
||||
ILibRemoteLogging_Dispatch_Update(obj, module, "ENABLED", userContext);
|
||||
}
|
||||
}
|
||||
else if(module != 0x00)
|
||||
{
|
||||
// Module Specific Commands
|
||||
ILibRemoteLogging_OnCommand command = obj->CommandSink[ILibWhichPowerOfTwo((int)module)];
|
||||
sem_post(&(obj->LogSyncLock));
|
||||
if(command!=NULL)
|
||||
{
|
||||
command(loggingModule, (ILibRemoteLogging_Modules)module, flags, data+4, dataLen-4, userContext);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sem_post(&(obj->LogSyncLock));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
typedef struct ILibRemoteLogging_FileTransport
|
||||
{
|
||||
ILibTransport transport;
|
||||
ILibLinkedList_FileBacked_Root *logFile;
|
||||
char* localFilePath;
|
||||
int enabled;
|
||||
ILibRemoteLogging_Module* parent;
|
||||
}ILibRemoteLogging_FileTransport;
|
||||
|
||||
ILibTransport_DoneState ILibFileTransport_SendSink(void *transport, char* buffer, int bufferLength, ILibTransport_MemoryOwnership ownership, ILibTransport_DoneState done)
|
||||
{
|
||||
ILibRemoteLogging_FileTransport *ft = (ILibRemoteLogging_FileTransport*)transport;
|
||||
|
||||
if (ft->logFile != NULL && ft->enabled != 0)
|
||||
{
|
||||
ILibLinkedList_FileBacked_AddTail(ft->logFile, buffer, bufferLength);
|
||||
}
|
||||
return(ILibTransport_DoneState_COMPLETE);
|
||||
}
|
||||
unsigned int ILibFileTransport_PendingBytes(void *transport)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(transport);
|
||||
return 0;
|
||||
}
|
||||
void ILibFileTransport_CloseSink(void* transport)
|
||||
{
|
||||
ILibRemoteLogging_FileTransport *ft = (ILibRemoteLogging_FileTransport*)transport;
|
||||
|
||||
ILibRemoteLogging_DeleteUserContext(ft->parent, transport);
|
||||
if (ft->logFile != NULL) { ILibLinkedList_FileBacked_Close(ft->logFile); }
|
||||
if (ft->localFilePath != NULL) { free(ft->localFilePath); }
|
||||
free(transport);
|
||||
}
|
||||
int ILibRemoteLogging_FileTransport_ReadLogs(ILibRemoteLogging_FileTransport* ft, void *userContext)
|
||||
{
|
||||
ILibLinkedList_FileBacked_Node *node = NULL;
|
||||
|
||||
if (ILibLinkedList_FileBacked_IsEmpty(ft->logFile) != 0)
|
||||
{
|
||||
// No log entries
|
||||
return 1;
|
||||
}
|
||||
|
||||
while ((node = ILibLinkedList_FileBacked_ReadNext(ft->logFile, node)) != NULL)
|
||||
{
|
||||
ILibTransport_Send(userContext, node->data, node->dataLen, ILibTransport_MemoryOwnership_USER, ILibTransport_DoneState_COMPLETE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ILibRemoteLogging_FileTransport_Report(void* userContext, ILibRemoteLogging_FileTransport *ft)
|
||||
{
|
||||
int len;
|
||||
char buf[72];
|
||||
|
||||
unsigned short newModules = 0;
|
||||
unsigned short flags = 0;
|
||||
|
||||
((unsigned short*)buf)[0] = htons((unsigned short)ILibRemoteLogging_Modules_Logger | (unsigned short)0x8000);
|
||||
((unsigned short*)buf)[1] = htons(ILibRemoteLogging_Flags_VerbosityLevel_1);
|
||||
|
||||
if (ft->logFile == NULL)
|
||||
{
|
||||
len = sprintf_s(buf + 4, sizeof(buf) - 4, "*** ILibRemoteLogging_FileTransport [No Logfile Set] ***");
|
||||
ILibTransport_Send(userContext, buf, len + 4, ILibTransport_MemoryOwnership_USER, ILibTransport_DoneState_COMPLETE);
|
||||
return;
|
||||
}
|
||||
|
||||
ILibLinkedList_FileBacked_ReloadRoot(ft->logFile);
|
||||
newModules = (unsigned short)(ft->logFile->flags & 0xFFFF);
|
||||
flags = (unsigned short)((ft->logFile->flags >> 16) & 0x3F);
|
||||
|
||||
len = sprintf_s(buf + 4, sizeof(buf) - 4, "*** Verbosity = %d ***", ILibWhichPowerOfTwo((int)flags));
|
||||
ILibTransport_Send(userContext, buf, len + 4, ILibTransport_MemoryOwnership_USER, ILibTransport_DoneState_COMPLETE);
|
||||
|
||||
if ((newModules & ILibRemoteLogging_Modules_WebRTC_STUN_ICE) == ILibRemoteLogging_Modules_WebRTC_STUN_ICE)
|
||||
{
|
||||
len = sprintf_s(buf + 4, sizeof(buf) - 4, "...WebRTC [STUN/ICE]");
|
||||
ILibTransport_Send(userContext, buf, len + 4, ILibTransport_MemoryOwnership_USER, ILibTransport_DoneState_COMPLETE);
|
||||
}
|
||||
if ((newModules & ILibRemoteLogging_Modules_WebRTC_DTLS) == ILibRemoteLogging_Modules_WebRTC_DTLS)
|
||||
{
|
||||
len = sprintf_s(buf + 4, sizeof(buf) - 4, "...WebRTC [DTLS]");
|
||||
ILibTransport_Send(userContext, buf, len + 4, ILibTransport_MemoryOwnership_USER, ILibTransport_DoneState_COMPLETE);
|
||||
}
|
||||
if ((newModules & ILibRemoteLogging_Modules_WebRTC_SCTP) == ILibRemoteLogging_Modules_WebRTC_SCTP)
|
||||
{
|
||||
len = sprintf_s(buf + 4, sizeof(buf) - 4, "...WebRTC [SCTP]");
|
||||
ILibTransport_Send(userContext, buf, len + 4, ILibTransport_MemoryOwnership_USER, ILibTransport_DoneState_COMPLETE);
|
||||
}
|
||||
if ((newModules & ILibRemoteLogging_Modules_Agent_GuardPost) == ILibRemoteLogging_Modules_Agent_GuardPost)
|
||||
{
|
||||
len = sprintf_s(buf + 4, sizeof(buf) - 4, "...MeshAgent [GUARDPOST]");
|
||||
ILibTransport_Send(userContext, buf, len + 4, ILibTransport_MemoryOwnership_USER, ILibTransport_DoneState_COMPLETE);
|
||||
}
|
||||
if ((newModules & ILibRemoteLogging_Modules_Agent_KVM) == ILibRemoteLogging_Modules_Agent_KVM)
|
||||
{
|
||||
len = sprintf_s(buf + 4, sizeof(buf) - 4, "...MeshAgent [KVM]");
|
||||
ILibTransport_Send(userContext, buf, len + 4, ILibTransport_MemoryOwnership_USER, ILibTransport_DoneState_COMPLETE);
|
||||
}
|
||||
if ((newModules & ILibRemoteLogging_Modules_Agent_P2P) == ILibRemoteLogging_Modules_Agent_P2P)
|
||||
{
|
||||
len = sprintf_s(buf + 4, sizeof(buf) - 4, "...MeshAgent [P2P]");
|
||||
ILibTransport_Send(userContext, buf, len + 4, ILibTransport_MemoryOwnership_USER, ILibTransport_DoneState_COMPLETE);
|
||||
}
|
||||
if ((newModules & ILibRemoteLogging_Modules_Microstack_AsyncSocket) == ILibRemoteLogging_Modules_Microstack_AsyncSocket)
|
||||
{
|
||||
len = sprintf_s(buf + 4, sizeof(buf) - 4, "...Microstack [AsyncSocket]");
|
||||
ILibTransport_Send(userContext, buf, len + 4, ILibTransport_MemoryOwnership_USER, ILibTransport_DoneState_COMPLETE);
|
||||
}
|
||||
if ((newModules & ILibRemoteLogging_Modules_Microstack_Web) == ILibRemoteLogging_Modules_Microstack_Web)
|
||||
{
|
||||
len = sprintf_s(buf + 4, sizeof(buf) - 4, "...Microstack [WebServer]");
|
||||
ILibTransport_Send(userContext, buf, len + 4, ILibTransport_MemoryOwnership_USER, ILibTransport_DoneState_COMPLETE);
|
||||
}
|
||||
if ((newModules & ILibRemoteLogging_Modules_Microstack_Pipe) == ILibRemoteLogging_Modules_Microstack_Pipe)
|
||||
{
|
||||
len = sprintf_s(buf + 4, sizeof(buf) - 4, "...Microstack [Pipe]");
|
||||
ILibTransport_Send(userContext, buf, len + 4, ILibTransport_MemoryOwnership_USER, ILibTransport_DoneState_COMPLETE);
|
||||
}
|
||||
if ((newModules & ILibRemoteLogging_Modules_Microstack_Generic) == ILibRemoteLogging_Modules_Microstack_Generic)
|
||||
{
|
||||
len = sprintf_s(buf + 4, sizeof(buf) - 4, "...Microstack [Generic]");
|
||||
ILibTransport_Send(userContext, buf, len + 4, ILibTransport_MemoryOwnership_USER, ILibTransport_DoneState_COMPLETE);
|
||||
}
|
||||
}
|
||||
|
||||
void ILibRemoteLogging_FileTransport_CommandSink(ILibRemoteLogging sender, ILibRemoteLogging_Modules module, unsigned short flags, char* data, int dataLen, void *userContext)
|
||||
{
|
||||
ILibRemoteLogging_Module *obj = (ILibRemoteLogging_Module*)sender;
|
||||
int i, len;
|
||||
char buf[72];
|
||||
|
||||
sem_wait(&(obj->LogSyncLock));
|
||||
for (i = 0; i < (sizeof(obj->Sessions) / sizeof(ILibRemoteLogging_Session)); ++i)
|
||||
{
|
||||
if (obj->Sessions[i].UserContext == NULL) { break; } // End of Sessions
|
||||
if (((ILibTransport*)obj->Sessions[i].UserContext)->IdentifierFlags == ILibTransports_RemoteLogging_FileTransport)
|
||||
{
|
||||
ILibRemoteLogging_FileTransport *ft = (ILibRemoteLogging_FileTransport*)obj->Sessions[i].UserContext;
|
||||
// This command applies to this type of ILibTransport
|
||||
|
||||
|
||||
if ((flags & ILibRemoteLogging_Command_Logger_Flags_ENABLE) == ILibRemoteLogging_Command_Logger_Flags_ENABLE)
|
||||
{
|
||||
switch (data[0])
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
// Enable/Disable
|
||||
ILibLinkedList_FileBacked_ReloadRoot(ft->logFile);
|
||||
ft->logFile->flags &= (unsigned int)0x7FFFFFFF;
|
||||
ft->enabled = data[0];
|
||||
if (ft->enabled != 0)
|
||||
{
|
||||
ft->logFile->flags |= (unsigned int)0x80000000;
|
||||
}
|
||||
ILibLinkedList_FileBacked_SaveRoot(ft->logFile);
|
||||
|
||||
((unsigned short*)buf)[0] = htons((unsigned short)ILibRemoteLogging_Modules_Logger | (unsigned short)0x8000);
|
||||
((unsigned short*)buf)[1] = htons(ILibRemoteLogging_Flags_VerbosityLevel_1);
|
||||
len = sprintf_s(buf + 4, sizeof(buf) - 4, "ILibRemoteLogging_FileTransport [%s]", ft->enabled == 0 ? "DISABLED" : "ENABLED");
|
||||
ILibTransport_Send(userContext, buf, len + 4, ILibTransport_MemoryOwnership_USER, ILibTransport_DoneState_COMPLETE);
|
||||
if (ft->enabled != 0)
|
||||
{
|
||||
ILibRemoteLogging_FileTransport_Report(userContext, ft);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
// Return the current state
|
||||
((unsigned short*)buf)[0] = htons(ILibRemoteLogging_Modules_Logger);
|
||||
((unsigned short*)buf)[1] = htons(ILibRemoteLogging_Command_Logger_Flags_ENABLE);
|
||||
buf[4] = ft->enabled == 0 ? 0 : 1;
|
||||
ILibTransport_Send(userContext, buf, 5, ILibTransport_MemoryOwnership_USER, ILibTransport_DoneState_COMPLETE);
|
||||
if (ft->enabled != 0)
|
||||
{
|
||||
ILibRemoteLogging_FileTransport_Report(userContext, ft);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags & ILibRemoteLogging_Command_Logger_Flags_READ_FILE) == ILibRemoteLogging_Command_Logger_Flags_READ_FILE)
|
||||
{
|
||||
if (ILibRemoteLogging_FileTransport_ReadLogs(ft, userContext) != 0)
|
||||
{
|
||||
((unsigned short*)buf)[0] = htons((unsigned short)ILibRemoteLogging_Modules_Logger | (unsigned short)0x8000);
|
||||
((unsigned short*)buf)[1] = htons(ILibRemoteLogging_Flags_VerbosityLevel_1);
|
||||
len = sprintf_s(buf + 4, sizeof(buf) - 4, "ILibRemoteLogging_FileTransport: (No Log Entries)");
|
||||
ILibTransport_Send(userContext, buf, len + 4, ILibTransport_MemoryOwnership_USER, ILibTransport_DoneState_COMPLETE);
|
||||
}
|
||||
}
|
||||
if ((flags & ILibRemoteLogging_Command_Logger_Flags_RESET_FILE) == ILibRemoteLogging_Command_Logger_Flags_RESET_FILE)
|
||||
{
|
||||
// Clear the Log File
|
||||
if (ft->logFile != NULL)
|
||||
{
|
||||
ILibLinkedList_FileBacked_Reset(ft->logFile);
|
||||
|
||||
((unsigned short*)buf)[0] = htons((unsigned short)ILibRemoteLogging_Modules_Logger | (unsigned short)0x8000);
|
||||
((unsigned short*)buf)[1] = htons(ILibRemoteLogging_Flags_VerbosityLevel_1);
|
||||
len = sprintf_s(buf + 4, sizeof(buf) - 4, "ILibRemoteLogging_FileTransport: (Logfile was reset)");
|
||||
ILibTransport_Send(userContext, buf, len + 4, ILibTransport_MemoryOwnership_USER, ILibTransport_DoneState_COMPLETE);
|
||||
}
|
||||
else
|
||||
{
|
||||
((unsigned short*)buf)[0] = htons((unsigned short)ILibRemoteLogging_Modules_Logger | (unsigned short)0x8000);
|
||||
((unsigned short*)buf)[1] = htons(ILibRemoteLogging_Flags_VerbosityLevel_1);
|
||||
len = sprintf_s(buf + 4, sizeof(buf) - 4, "ILibRemoteLogging_FileTransport: (No Log File)");
|
||||
ILibTransport_Send(userContext, buf, len + 4, ILibTransport_MemoryOwnership_USER, ILibTransport_DoneState_COMPLETE);
|
||||
}
|
||||
}
|
||||
if ((flags & ILibRemoteLogging_Command_Logger_Flags_RESET_FLAGS) == ILibRemoteLogging_Command_Logger_Flags_RESET_FLAGS)
|
||||
{
|
||||
if (dataLen == 4 && ft->logFile != NULL)
|
||||
{
|
||||
unsigned short newModules = ntohs(((unsigned short*)data)[0]);
|
||||
unsigned short newFlags = ntohs(((unsigned short*)data)[1]);
|
||||
obj->Sessions[i].Flags = (newFlags & 0x3F) << 16;
|
||||
obj->Sessions[i].Flags |= (unsigned int)newModules;
|
||||
|
||||
ILibLinkedList_FileBacked_ReloadRoot(ft->logFile);
|
||||
ft->logFile->flags = (unsigned int)ft->enabled << 31;
|
||||
ft->logFile->flags |= (obj->Sessions[i].Flags & 0x7FFFFFFF);
|
||||
ILibLinkedList_FileBacked_SaveRoot(ft->logFile);
|
||||
|
||||
((unsigned short*)buf)[0] = htons((unsigned short)ILibRemoteLogging_Modules_Logger | (unsigned short)0x8000);
|
||||
((unsigned short*)buf)[1] = htons(ILibRemoteLogging_Flags_VerbosityLevel_1);
|
||||
len = sprintf_s(buf + 4, sizeof(buf) - 4, "ILibRemoteLogging_FileTransport: (LogFile Flags RESET)");
|
||||
ILibTransport_Send(userContext, buf, len + 4, ILibTransport_MemoryOwnership_USER, ILibTransport_DoneState_COMPLETE);
|
||||
|
||||
ILibRemoteLogging_FileTransport_Report(userContext, ft);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sem_post(&(obj->LogSyncLock));
|
||||
}
|
||||
ILibTransport* ILibRemoteLogging_CreateFileTransport(ILibRemoteLogging loggingModule, ILibRemoteLogging_Modules modules, ILibRemoteLogging_Flags flags, char* path, int pathLen)
|
||||
{
|
||||
ILibRemoteLogging_FileTransport *retVal = ILibMemory_Allocate(sizeof(ILibRemoteLogging_FileTransport), 0, NULL, NULL);
|
||||
char data[4];
|
||||
|
||||
if (pathLen < 0) { pathLen = (int)strnlen_s(path, _MAX_PATH); }
|
||||
retVal->transport.IdentifierFlags = (int)ILibTransports_RemoteLogging_FileTransport;
|
||||
retVal->transport.SendPtr = ILibFileTransport_SendSink;
|
||||
retVal->transport.PendingBytesPtr = ILibFileTransport_PendingBytes;
|
||||
retVal->transport.ClosePtr = ILibFileTransport_CloseSink;
|
||||
retVal->parent = (ILibRemoteLogging_Module*)loggingModule;
|
||||
retVal->localFilePath = ILibString_Copy(path, pathLen);
|
||||
|
||||
retVal->logFile = ILibLinkedList_FileBacked_Create(retVal->localFilePath, 2048000, 4096);
|
||||
if (retVal->logFile->flags != 0)
|
||||
{
|
||||
modules = (unsigned short)(retVal->logFile->flags & 0xFFFF);
|
||||
flags = (unsigned short)(retVal->logFile->flags >> 16);
|
||||
retVal->enabled = ((flags & 0x8000) == 0x8000) ? 1 : 0;
|
||||
}
|
||||
|
||||
((unsigned short*)data)[0] = htons((unsigned short)modules);
|
||||
((unsigned short*)data)[1] = htons((unsigned short)flags & (unsigned short)0x3F);
|
||||
|
||||
ILibRemoteLogging_Dispatch(loggingModule, data, (int)sizeof(data), retVal);
|
||||
ILibRemoteLogging_RegisterCommandSink(loggingModule, ILibRemoteLogging_Modules_Logger, ILibRemoteLogging_FileTransport_CommandSink);
|
||||
return((ILibTransport*)retVal);
|
||||
}
|
||||
|
||||
#endif
|
||||
103
microstack/ILibRemoteLogging.h
Normal file
103
microstack/ILibRemoteLogging.h
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
Copyright 2006 - 2017 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under 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);
|
||||
char* ILibRemoteLogging_ConvertAddress(struct sockaddr* addr);
|
||||
|
||||
#ifdef _REMOTELOGGING
|
||||
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_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
|
||||
450
microstack/ILibSimpleDataStore.c
Normal file
450
microstack/ILibSimpleDataStore.c
Normal file
@@ -0,0 +1,450 @@
|
||||
/*
|
||||
Copyright 2006 - 2017 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ILibSimpleDataStore.h"
|
||||
#include "ILibCrypto.h"
|
||||
#ifndef WIN32
|
||||
#include <sys/file.h>
|
||||
#endif
|
||||
|
||||
#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(_MINCORE)
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include <crtdbg.h>
|
||||
#endif
|
||||
|
||||
#define SHA256HASHSIZE 32
|
||||
|
||||
#ifdef _WIN64
|
||||
#define ILibSimpleDataStore_GetPosition(filePtr) _ftelli64(filePtr)
|
||||
#define ILibSimpleDataStore_SeekPosition(filePtr, position, seekMode) _fseeki64(filePtr, position, seekMode)
|
||||
typedef long long DS_Long;
|
||||
#else
|
||||
#define ILibSimpleDataStore_GetPosition(filePtr) ftell(filePtr)
|
||||
#define ILibSimpleDataStore_SeekPosition(filePtr, position, seekMode) fseek(filePtr, position, seekMode)
|
||||
typedef long DS_Long;
|
||||
#endif
|
||||
|
||||
typedef struct ILibSimpleDataStore_Root
|
||||
{
|
||||
FILE* dataFile;
|
||||
char* filePath;
|
||||
char scratchPad[4096];
|
||||
ILibHashtable keyTable; // keys --> ILibSimpleDataStore_TableEntry
|
||||
DS_Long fileSize;
|
||||
int error;
|
||||
} ILibSimpleDataStore_Root;
|
||||
|
||||
/* File Format
|
||||
------------------------------------------
|
||||
4 Bytes - Node size
|
||||
4 Bytes - Key length
|
||||
4 Bytes - Value length
|
||||
32 Bytes - SHA256 hash check value
|
||||
Variable - Key
|
||||
Variable - Value
|
||||
------------------------------------------ */
|
||||
|
||||
typedef struct ILibSimpleDataStore_RecordHeader
|
||||
{
|
||||
int nodeSize;
|
||||
int keyLen;
|
||||
int valueLength;
|
||||
char hash[SHA256HASHSIZE];
|
||||
} ILibSimpleDataStore_RecordHeader;
|
||||
|
||||
typedef struct ILibSimpleDataStore_RecordNode
|
||||
{
|
||||
int nodeSize;
|
||||
int keyLen;
|
||||
int valueLength;
|
||||
char valueHash[SHA256HASHSIZE];
|
||||
DS_Long valueOffset;
|
||||
char key[];
|
||||
} ILibSimpleDataStore_RecordNode;
|
||||
|
||||
typedef struct ILibSimpleDataStore_TableEntry
|
||||
{
|
||||
int valueLength;
|
||||
char valueHash[SHA256HASHSIZE];
|
||||
DS_Long valueOffset;
|
||||
} ILibSimpleDataStore_TableEntry;
|
||||
|
||||
const int ILibMemory_SimpleDataStore_CONTAINERSIZE = sizeof(ILibSimpleDataStore_Root);
|
||||
|
||||
// Perform a SHA256 hash of some data
|
||||
void ILibSimpleDataStore_SHA256(char *data, int datalen, char* result) { util_sha256(data, datalen, result); }
|
||||
|
||||
// Write a key/value pair to file, the hash is already calculated
|
||||
DS_Long ILibSimpleDataStore_WriteRecord(FILE *f, char* key, int keyLen, char* value, int valueLen, char* hash)
|
||||
{
|
||||
char headerBytes[sizeof(ILibSimpleDataStore_RecordNode)];
|
||||
ILibSimpleDataStore_RecordHeader *header = (ILibSimpleDataStore_RecordHeader*)headerBytes;
|
||||
DS_Long offset;
|
||||
|
||||
fseek(f, 0, SEEK_END);
|
||||
header->nodeSize = htonl(sizeof(ILibSimpleDataStore_RecordNode) + keyLen + valueLen);
|
||||
header->keyLen = htonl(keyLen);
|
||||
header->valueLength = htonl(valueLen);
|
||||
if (hash != NULL) { memcpy_s(header->hash, sizeof(header->hash), hash, SHA256HASHSIZE); } else { memset(header->hash, 0, SHA256HASHSIZE); }
|
||||
|
||||
if (fwrite(headerBytes, 1, sizeof(ILibSimpleDataStore_RecordNode), f)) {}
|
||||
if (fwrite(key, 1, keyLen, f)) {}
|
||||
offset = ILibSimpleDataStore_GetPosition(f);
|
||||
if (value != NULL) { if (fwrite(value, 1, valueLen, f)) {} }
|
||||
fflush(f);
|
||||
return offset;
|
||||
}
|
||||
|
||||
// Read the next record in the file
|
||||
ILibSimpleDataStore_RecordNode* ILibSimpleDataStore_ReadNextRecord(ILibSimpleDataStore_Root *root)
|
||||
{
|
||||
SHA256_CTX c;
|
||||
char data[4096];
|
||||
char result[SHA256HASHSIZE];
|
||||
int i, bytesLeft;
|
||||
ILibSimpleDataStore_RecordNode *node = (ILibSimpleDataStore_RecordNode*)(root->scratchPad );
|
||||
|
||||
// If the current position is the end of the file, exit now.
|
||||
if (ILibSimpleDataStore_GetPosition(root->dataFile) == root->fileSize) { return NULL; }
|
||||
|
||||
// Read sizeof(ILibSimpleDataStore_RecordNode) bytes to get record Size
|
||||
i = (int)fread((void*)node, 1, sizeof(ILibSimpleDataStore_RecordNode), root->dataFile);
|
||||
if (i < sizeof(ILibSimpleDataStore_RecordNode)) { return NULL; }
|
||||
|
||||
// Correct the struct, valueHash stays the same
|
||||
node->nodeSize = (int)ntohl(node->nodeSize);
|
||||
node->keyLen = (int)ntohl(node->keyLen);
|
||||
node->valueLength = (int)ntohl(node->valueLength);
|
||||
node->valueOffset = ILibSimpleDataStore_GetPosition(root->dataFile) + (DS_Long)node->keyLen;
|
||||
|
||||
// Read the key name
|
||||
i = (int)fread((char*)node + sizeof(ILibSimpleDataStore_RecordNode), 1, node->keyLen, root->dataFile);
|
||||
if (i != node->keyLen) { return NULL; } // Reading Key Failed
|
||||
|
||||
// Validate Data, in 4k chunks at a time
|
||||
bytesLeft = node->valueLength;
|
||||
|
||||
// Hash SHA256 the data
|
||||
SHA256_Init(&c);
|
||||
while (bytesLeft > 0)
|
||||
{
|
||||
i = (int)fread(data, 1, bytesLeft > 4096 ? 4096 : bytesLeft, root->dataFile);
|
||||
if (i <= 0) { bytesLeft = 0; break; }
|
||||
SHA256_Update(&c, data, i);
|
||||
bytesLeft -= i;
|
||||
}
|
||||
SHA256_Final((unsigned char*)result, &c);
|
||||
if (node->valueLength > 0)
|
||||
{
|
||||
// Check the hash
|
||||
if (memcmp(node->valueHash, result, SHA256HASHSIZE) == 0) {
|
||||
return node; // Data is correct
|
||||
}
|
||||
return NULL; // Data is corrupt
|
||||
}
|
||||
else
|
||||
{
|
||||
return(node);
|
||||
}
|
||||
}
|
||||
|
||||
// ???
|
||||
void ILibSimpleDataStore_TableClear_Sink(ILibHashtable sender, void *Key1, char* Key2, int Key2Len, void *Data, void *user)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(sender);
|
||||
UNREFERENCED_PARAMETER(Key1);
|
||||
UNREFERENCED_PARAMETER(Key2);
|
||||
UNREFERENCED_PARAMETER(Key2Len);
|
||||
UNREFERENCED_PARAMETER(user);
|
||||
|
||||
free(Data);
|
||||
}
|
||||
|
||||
// Rebuild the in-memory key to record table, done when starting up the data store
|
||||
void ILibSimpleDataStore_RebuildKeyTable(ILibSimpleDataStore_Root *root)
|
||||
{
|
||||
ILibSimpleDataStore_RecordNode *node = NULL;
|
||||
ILibSimpleDataStore_TableEntry *entry;
|
||||
|
||||
ILibHashtable_ClearEx(root->keyTable, ILibSimpleDataStore_TableClear_Sink, root); // Wipe the key table, we will rebulit it
|
||||
fseek(root->dataFile, 0, SEEK_SET); // See the start of the file
|
||||
root->fileSize = -1; // Indicate we can't write to the data store
|
||||
|
||||
// Start reading records
|
||||
while ((node = ILibSimpleDataStore_ReadNextRecord(root)) != NULL)
|
||||
{
|
||||
// Get the entry from the memory table
|
||||
entry = (ILibSimpleDataStore_TableEntry*)ILibHashtable_Get(root->keyTable, NULL, node->key, node->keyLen);
|
||||
if (node->valueLength > 0)
|
||||
{
|
||||
// If the value is not empty, we need to create/overwrite this value in memory
|
||||
if (entry == NULL) { entry = (ILibSimpleDataStore_TableEntry*)ILibMemory_Allocate(sizeof(ILibSimpleDataStore_TableEntry), 0, NULL, NULL); }
|
||||
memcpy_s(entry->valueHash, sizeof(entry->valueHash), node->valueHash, SHA256HASHSIZE);
|
||||
entry->valueLength = node->valueLength;
|
||||
entry->valueOffset = node->valueOffset;
|
||||
ILibHashtable_Put(root->keyTable, NULL, node->key, node->keyLen, entry);
|
||||
}
|
||||
else if (entry != NULL)
|
||||
{
|
||||
// If value is empty, remove the in-memory entry.
|
||||
ILibHashtable_Remove(root->keyTable, NULL, node->key, node->keyLen);
|
||||
free(entry);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the size of the entire data store file
|
||||
root->fileSize = ILibSimpleDataStore_GetPosition(root->dataFile);
|
||||
}
|
||||
|
||||
// Open the data store file
|
||||
FILE* ILibSimpleDataStore_OpenFileEx(char* filePath, int forceTruncateIfNonZero)
|
||||
{
|
||||
FILE* f = NULL;
|
||||
|
||||
#ifdef WIN32
|
||||
if (forceTruncateIfNonZero !=0 || fopen_s(&f, filePath, "rb+N") != 0)
|
||||
{
|
||||
fopen_s(&f, filePath, "wb+N");
|
||||
}
|
||||
#else
|
||||
if (forceTruncateIfNonZero != 0 || (f = fopen(filePath, "rb+")) == NULL)
|
||||
{
|
||||
f = fopen(filePath, "wb+");
|
||||
}
|
||||
if (flock(fileno(f), LOCK_EX | LOCK_NB) != 0) { fclose(f); return NULL; } // Request exclusive lock on this file, no blocking.
|
||||
#endif
|
||||
|
||||
return f;
|
||||
}
|
||||
#define ILibSimpleDataStore_OpenFile(filePath) ILibSimpleDataStore_OpenFileEx(filePath, 0)
|
||||
|
||||
// Open the data store file. Optionally allocate spare user memory
|
||||
__EXPORT_TYPE ILibSimpleDataStore ILibSimpleDataStore_CreateEx(char* filePath, int userExtraMemorySize)
|
||||
{
|
||||
ILibSimpleDataStore_Root* retVal = (ILibSimpleDataStore_Root*)ILibMemory_Allocate(ILibMemory_SimpleDataStore_CONTAINERSIZE, userExtraMemorySize, NULL, NULL);
|
||||
|
||||
retVal->filePath = ILibString_Copy(filePath, (int)strnlen_s(filePath, ILibSimpleDataStore_MaxFilePath));
|
||||
retVal->dataFile = ILibSimpleDataStore_OpenFile(retVal->filePath);
|
||||
|
||||
if (retVal->dataFile == NULL)
|
||||
{
|
||||
free(retVal->filePath);
|
||||
free(retVal);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
retVal->keyTable = ILibHashtable_Create();
|
||||
ILibSimpleDataStore_RebuildKeyTable(retVal);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
// Close the data store file
|
||||
__EXPORT_TYPE void ILibSimpleDataStore_Close(ILibSimpleDataStore dataStore)
|
||||
{
|
||||
ILibSimpleDataStore_Root *root = (ILibSimpleDataStore_Root*)dataStore;
|
||||
ILibHashtable_DestroyEx(root->keyTable, ILibSimpleDataStore_TableClear_Sink, root);
|
||||
|
||||
free(root->filePath);
|
||||
fclose(root->dataFile);
|
||||
free(root);
|
||||
}
|
||||
|
||||
// Store a key/value pair in the data store
|
||||
__EXPORT_TYPE int ILibSimpleDataStore_PutEx(ILibSimpleDataStore dataStore, char* key, int keyLen, char* value, int valueLen)
|
||||
{
|
||||
char hash[SHA256HASHSIZE];
|
||||
ILibSimpleDataStore_Root *root = (ILibSimpleDataStore_Root*)dataStore;
|
||||
ILibSimpleDataStore_TableEntry *entry = (ILibSimpleDataStore_TableEntry*)ILibHashtable_Get(root->keyTable, NULL, key, keyLen);
|
||||
ILibSimpleDataStore_SHA256(value, valueLen, hash); // Hash the value
|
||||
|
||||
// Create a new record for the key and value
|
||||
if (entry == NULL) {
|
||||
entry = (ILibSimpleDataStore_TableEntry*)ILibMemory_Allocate(sizeof(ILibSimpleDataStore_TableEntry), 0, NULL, NULL); }
|
||||
else {
|
||||
if (memcmp(entry->valueHash, hash, SHA256HASHSIZE) == 0) { return 0; }
|
||||
}
|
||||
|
||||
memcpy_s(entry->valueHash, sizeof(entry->valueHash), hash, SHA256HASHSIZE);
|
||||
entry->valueLength = valueLen;
|
||||
entry->valueOffset = ILibSimpleDataStore_WriteRecord(root->dataFile, key, keyLen, value, valueLen, entry->valueHash); // Write the key and value
|
||||
root->fileSize = ILibSimpleDataStore_GetPosition(root->dataFile); // Update the size of the data store;
|
||||
|
||||
// Add the record to the data store
|
||||
return ILibHashtable_Put(root->keyTable, NULL, key, keyLen, entry) == NULL ? 0 : 1;
|
||||
}
|
||||
|
||||
// Get a value from the data store given a key
|
||||
__EXPORT_TYPE int ILibSimpleDataStore_GetEx(ILibSimpleDataStore dataStore, char* key, int keyLen, char *buffer, int bufferLen)
|
||||
{
|
||||
char hash[32];
|
||||
ILibSimpleDataStore_Root *root = (ILibSimpleDataStore_Root*)dataStore;
|
||||
ILibSimpleDataStore_TableEntry *entry = (ILibSimpleDataStore_TableEntry*)ILibHashtable_Get(root->keyTable, NULL, key, keyLen);
|
||||
|
||||
if (entry == NULL) return 0; // If there is no in-memory entry for this key, return zero now.
|
||||
if ((buffer != NULL) && (bufferLen >= entry->valueLength)) // If the buffer is not null and can hold the value, place the value in the buffer.
|
||||
{
|
||||
if (ILibSimpleDataStore_SeekPosition(root->dataFile, entry->valueOffset, SEEK_SET) != 0) return 0; // Seek to the position of the value in the data store
|
||||
if (fread(buffer, 1, entry->valueLength, root->dataFile) == 0) return 0; // Read the value into the buffer
|
||||
util_sha256(buffer, entry->valueLength, hash); // Compute the hash of the read value
|
||||
if (memcmp(hash, entry->valueHash, SHA256HASHSIZE) != 0) return 0; // Check the hash, return 0 if not valid
|
||||
if (bufferLen > entry->valueLength) { buffer[entry->valueLength] = 0; } // Add a zero at the end to be nice, if the buffer can take it.
|
||||
}
|
||||
return entry->valueLength;
|
||||
}
|
||||
|
||||
// Get the reference to the SHA256 hash value from the datastore for a given a key.
|
||||
__EXPORT_TYPE char* ILibSimpleDataStore_GetHashEx(ILibSimpleDataStore dataStore, char* key, int keyLen)
|
||||
{
|
||||
ILibSimpleDataStore_Root *root = (ILibSimpleDataStore_Root*)dataStore;
|
||||
ILibSimpleDataStore_TableEntry *entry = (ILibSimpleDataStore_TableEntry*)ILibHashtable_Get(root->keyTable, NULL, key, keyLen);
|
||||
|
||||
if (entry == NULL) return NULL; // If there is no in-memory entry for this key, return zero now.
|
||||
return entry->valueHash;
|
||||
}
|
||||
|
||||
// Delete a key and value from the data store
|
||||
__EXPORT_TYPE int ILibSimpleDataStore_DeleteEx(ILibSimpleDataStore dataStore, char* key, int keyLen)
|
||||
{
|
||||
ILibSimpleDataStore_Root *root = (ILibSimpleDataStore_Root*)dataStore;
|
||||
ILibSimpleDataStore_TableEntry *entry = (ILibSimpleDataStore_TableEntry*)ILibHashtable_Remove(root->keyTable, NULL, key, keyLen);
|
||||
if (entry != NULL) { ILibSimpleDataStore_WriteRecord(root->dataFile, key, keyLen, NULL, 0, NULL); free(entry); return 1; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Lock the data store file
|
||||
__EXPORT_TYPE void ILibSimpleDataStore_Lock(ILibSimpleDataStore dataStore)
|
||||
{
|
||||
ILibSimpleDataStore_Root *root = (ILibSimpleDataStore_Root*)dataStore;
|
||||
ILibHashtable_Lock(root->keyTable);
|
||||
}
|
||||
|
||||
// Unlock the data store file
|
||||
__EXPORT_TYPE void ILibSimpleDataStore_UnLock(ILibSimpleDataStore dataStore)
|
||||
{
|
||||
ILibSimpleDataStore_Root *root = (ILibSimpleDataStore_Root*)dataStore;
|
||||
ILibHashtable_UnLock(root->keyTable);
|
||||
}
|
||||
|
||||
// Called by the compaction method, for each key in the enumeration we write the key/value to the temporary data store
|
||||
void ILibSimpleDataStore_Compact_EnumerateSink(ILibHashtable sender, void *Key1, char* Key2, int Key2Len, void *Data, void *user)
|
||||
{
|
||||
ILibSimpleDataStore_TableEntry *entry = (ILibSimpleDataStore_TableEntry*)Data;
|
||||
ILibSimpleDataStore_Root *root = (ILibSimpleDataStore_Root*)((void**)user)[0];
|
||||
FILE *compacted = (FILE*)((void**)user)[1];
|
||||
DS_Long offset;
|
||||
char value[4096];
|
||||
int valueLen;
|
||||
int bytesLeft = entry->valueLength;
|
||||
int totalBytesWritten = 0;
|
||||
int bytesWritten = 0;
|
||||
|
||||
if (root->error != 0) return; // There was an error, ABORT!
|
||||
|
||||
offset = ILibSimpleDataStore_WriteRecord(compacted, Key2, Key2Len, NULL, entry->valueLength, entry->valueHash);
|
||||
while (bytesLeft > 0)
|
||||
{
|
||||
if (ILibSimpleDataStore_SeekPosition(root->dataFile, entry->valueOffset + totalBytesWritten, SEEK_SET) == 0)
|
||||
{
|
||||
valueLen = (int)fread(value, 1, bytesLeft > 4096 ? 4096 : bytesLeft, root->dataFile);
|
||||
bytesWritten = (int)fwrite(value, 1, valueLen, compacted);
|
||||
if (bytesWritten != valueLen)
|
||||
{
|
||||
// Error
|
||||
root->error = 1;
|
||||
break;
|
||||
}
|
||||
totalBytesWritten += bytesWritten;
|
||||
bytesLeft -= valueLen;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Error
|
||||
root->error = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (root->error == 0) { entry->valueOffset = offset; }
|
||||
}
|
||||
|
||||
// Used to help with key enumeration
|
||||
void ILibSimpleDataStore_EnumerateKeysSink(ILibHashtable sender, void *Key1, char* Key2, int Key2Len, void *Data, void *user)
|
||||
{
|
||||
ILibSimpleDataStore_KeyEnumerationHandler handler = (ILibSimpleDataStore_KeyEnumerationHandler)((void**)user)[0];
|
||||
ILibSimpleDataStore_KeyEnumerationHandler dataStore = (ILibSimpleDataStore)((void**)user)[1];
|
||||
ILibSimpleDataStore_KeyEnumerationHandler userX = ((void**)user)[2];
|
||||
|
||||
UNREFERENCED_PARAMETER(sender);
|
||||
UNREFERENCED_PARAMETER(Key1);
|
||||
UNREFERENCED_PARAMETER(Key2);
|
||||
UNREFERENCED_PARAMETER(Key2Len);
|
||||
|
||||
handler(dataStore, Key2, Key2Len, userX); // Call the user
|
||||
}
|
||||
|
||||
// Enumerate each key in the data store, call the handler for each key
|
||||
__EXPORT_TYPE void ILibSimpleDataStore_EnumerateKeys(ILibSimpleDataStore dataStore, ILibSimpleDataStore_KeyEnumerationHandler handler, void * user)
|
||||
{
|
||||
void* users[3];
|
||||
ILibSimpleDataStore_Root *root = (ILibSimpleDataStore_Root*)dataStore;
|
||||
|
||||
users[0] = (void*)handler;
|
||||
users[1] = (void*)dataStore;
|
||||
users[2] = (void*)user;
|
||||
|
||||
if (handler != NULL) { ILibHashtable_Enumerate(root->keyTable, ILibSimpleDataStore_EnumerateKeysSink, users); }
|
||||
}
|
||||
|
||||
// Compact the data store
|
||||
__EXPORT_TYPE int ILibSimpleDataStore_Compact(ILibSimpleDataStore dataStore)
|
||||
{
|
||||
ILibSimpleDataStore_Root *root = (ILibSimpleDataStore_Root*)dataStore;
|
||||
char* tmp = ILibString_Cat(root->filePath, -1, ".tmp", -1); // Create the name of the temporary data store
|
||||
FILE* compacted;
|
||||
void* state[2];
|
||||
int retVal = 0;
|
||||
|
||||
// Start by opening a temporary .tmp file. Will be used to write the compacted data store.
|
||||
if ((compacted = ILibSimpleDataStore_OpenFileEx(tmp, 1)) == NULL) { free(tmp); return 1; }
|
||||
|
||||
// Enumerate all keys and write them all into the temporary data store
|
||||
state[0] = root;
|
||||
state[1] = compacted;
|
||||
root->error = 0;
|
||||
ILibHashtable_Enumerate(root->keyTable, ILibSimpleDataStore_Compact_EnumerateSink, state);
|
||||
|
||||
// Check if the enumeration went as planned
|
||||
if (root->error == 0)
|
||||
{
|
||||
// Success in writing new temporary file
|
||||
fclose(root->dataFile); // Close the data store
|
||||
fclose(compacted); // Close the temporary data store
|
||||
|
||||
// Now we copy the temporary data store over the data store, making it the new valid version
|
||||
#ifdef WIN32
|
||||
if (CopyFileA(tmp, root->filePath, FALSE) == FALSE) { retVal = 1; }
|
||||
DeleteFile(tmp);
|
||||
#else
|
||||
if (rename(tmp, root->filePath) != 0) { retVal = 1; }
|
||||
#endif
|
||||
|
||||
// We then open the newly compacted data store
|
||||
if ((root->dataFile = ILibSimpleDataStore_OpenFile(root->filePath)) != NULL) { root->fileSize = ILibSimpleDataStore_GetPosition(root->dataFile); } else { retVal = 1; }
|
||||
}
|
||||
|
||||
free(tmp); // Free the temporary file name
|
||||
return retVal; // Return 1 if we got an error, 0 if everything finished correctly
|
||||
}
|
||||
76
microstack/ILibSimpleDataStore.h
Normal file
76
microstack/ILibSimpleDataStore.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
Copyright 2006 - 2017 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
This is a simple data store that implements a hash table in a file. New keys are appended at the end of the file and the file can be compacted when needed.
|
||||
The store will automatically create a hash of each value and store the hash. Upon reading the data, the hash is always checked.
|
||||
*/
|
||||
|
||||
#ifndef __ILIBSIMPLEDATASTORE__
|
||||
#define __ILIBSIMPLEDATASTORE__
|
||||
|
||||
#include "ILibParsers.h"
|
||||
|
||||
#if defined(WIN32) && defined(EXPORT_LIB)
|
||||
#define __EXPORT_TYPE __declspec(dllexport)
|
||||
#else
|
||||
#define __EXPORT_TYPE
|
||||
#endif
|
||||
|
||||
#define ILibSimpleDataStore_MaxKeyLength 1024
|
||||
#define ILibSimpleDataStore_MaxUnspecifiedValueLen 16384
|
||||
#define ILibSimpleDataStore_MaxFilePath 4096
|
||||
|
||||
typedef void* ILibSimpleDataStore;
|
||||
|
||||
const extern int ILibMemory_SimpleDataStore_CONTAINERSIZE;
|
||||
|
||||
typedef void(*ILibSimpleDataStore_KeyEnumerationHandler)(ILibSimpleDataStore sender, char* Key, int KeyLen, void *user);
|
||||
|
||||
// Create the data store.
|
||||
__EXPORT_TYPE ILibSimpleDataStore ILibSimpleDataStore_CreateEx(char* filePath, int userExtraMemorySize);
|
||||
#define ILibSimpleDataStore_Create(filePath) ILibSimpleDataStore_CreateEx(filePath, 0)
|
||||
|
||||
// Close the data store.
|
||||
__EXPORT_TYPE void ILibSimpleDataStore_Close(ILibSimpleDataStore dataStore);
|
||||
|
||||
|
||||
__EXPORT_TYPE int ILibSimpleDataStore_PutEx(ILibSimpleDataStore dataStore, char* key, int keyLen, char* value, int valueLen);
|
||||
#define ILibSimpleDataStore_Put(dataStore, key, value) ILibSimpleDataStore_PutEx(dataStore, key, (int)strnlen_s(key, ILibSimpleDataStore_MaxKeyLength), value, (int)strnlen_s(value, ILibSimpleDataStore_MaxUnspecifiedValueLen))
|
||||
|
||||
// Get a value from the datastore of given a key.
|
||||
__EXPORT_TYPE int ILibSimpleDataStore_GetEx(ILibSimpleDataStore dataStore, char* key, int keyLen, char* buffer, int bufferLen);
|
||||
#define ILibSimpleDataStore_Get(dataStore, key, buffer, bufferLen) ILibSimpleDataStore_GetEx(dataStore, key, (int)strnlen_s(key, ILibSimpleDataStore_MaxKeyLength), buffer, bufferLen)
|
||||
|
||||
// Get the SHA256 hash value from the datastore for a given a key.
|
||||
__EXPORT_TYPE char* ILibSimpleDataStore_GetHashEx(ILibSimpleDataStore dataStore, char* key, int keyLen);
|
||||
#define ILibSimpleDataStore_GetHash(dataStore, key) ILibSimpleDataStore_GetHashEx(dataStore, key, (int)strnlen_s(key, ILibSimpleDataStore_MaxKeyLength))
|
||||
|
||||
// Delete a key from the data store
|
||||
__EXPORT_TYPE int ILibSimpleDataStore_DeleteEx(ILibSimpleDataStore dataStore, char* key, int keyLen);
|
||||
#define ILibSimpleDataStore_Delete(dataStore, key) ILibSimpleDataStore_DeleteEx(dataStore, key, (int)strnlen_s(key, ILibSimpleDataStore_MaxKeyLength))
|
||||
|
||||
// Enumerate all keys from the data store
|
||||
__EXPORT_TYPE void ILibSimpleDataStore_EnumerateKeys(ILibSimpleDataStore dataStore, ILibSimpleDataStore_KeyEnumerationHandler handler, void *user);
|
||||
|
||||
// Compacts the data store
|
||||
__EXPORT_TYPE int ILibSimpleDataStore_Compact(ILibSimpleDataStore dataStore);
|
||||
|
||||
// Lock and unlock the data store. This is useful if we need to access this store from many threads.
|
||||
__EXPORT_TYPE void ILibSimpleDataStore_Lock(ILibSimpleDataStore dataStore);
|
||||
__EXPORT_TYPE void ILibSimpleDataStore_UnLock(ILibSimpleDataStore dataStore);
|
||||
|
||||
#endif
|
||||
3727
microstack/ILibWebClient.c
Normal file
3727
microstack/ILibWebClient.c
Normal file
File diff suppressed because it is too large
Load Diff
319
microstack/ILibWebClient.h
Normal file
319
microstack/ILibWebClient.h
Normal file
@@ -0,0 +1,319 @@
|
||||
/*
|
||||
Copyright 2006 - 2017 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __ILibWebClient__
|
||||
#define __ILibWebClient__
|
||||
|
||||
#include "ILibParsers.h"
|
||||
#include "ILibAsyncSocket.h"
|
||||
#include "ILibCrypto.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*! \file ILibWebClient.h
|
||||
\brief MicroStack APIs for HTTP Client functionality
|
||||
*/
|
||||
|
||||
#define ILibWebClientIsStatusOk(statusCode) (statusCode>=200 && statusCode<=299)
|
||||
|
||||
/*! \defgroup ILibWebClient ILibWebClient Module
|
||||
\{
|
||||
*/
|
||||
|
||||
/*! \def WEBCLIENT_DESTROYED
|
||||
\brief The ILibWebClient object was destroyed
|
||||
*/
|
||||
#define WEBCLIENT_DESTROYED 5
|
||||
/*! \def WEBCLIENT_DELETED
|
||||
\brief The ILibWebClient object was deleted with a call to ILibWebClient_DeleteRequests
|
||||
*/
|
||||
#define WEBCLIENT_DELETED 6
|
||||
|
||||
#if defined(WIN32) || defined(_WIN32_WCE)
|
||||
#include <STDDEF.h>
|
||||
#elif defined(_POSIX)
|
||||
#if !defined(__APPLE__) && !defined(_VX_CPU)
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define WEBSOCKET_GUID "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
|
||||
#define WEBSOCKET_FIN 0x08000
|
||||
#define WEBSOCKET_RSV1 0x04000
|
||||
#define WEBSOCKET_RSV2 0x02000
|
||||
#define WEBSOCKET_RSV3 0x01000
|
||||
#define WEBSOCKET_OPCODE 0x00F00
|
||||
#define WEBSOCKET_MASK 0x00080
|
||||
#define WEBSOCKET_PLEN 0x0007F
|
||||
|
||||
#define WEBSOCKET_MAX_OUTPUT_FRAMESIZE 4096
|
||||
|
||||
#define WEBSOCKET_OPCODE_FRAMECONT 0x0
|
||||
#define WEBSOCKET_OPCODE_TEXTFRAME 0x1
|
||||
#define WEBSOCKET_OPCODE_BINARYFRAME 0x2
|
||||
#define WEBSOCKET_OPCODE_CLOSE 0x8
|
||||
#define WEBSOCKET_OPCODE_PING 0x9
|
||||
#define WEBSOCKET_OPCODE_PONG 0xA
|
||||
|
||||
enum ILibWebClient_DoneCode
|
||||
{
|
||||
ILibWebClient_DoneCode_NoErrors = 1,
|
||||
ILibWebClient_DoneCode_StillReading = 0,
|
||||
ILibWebClient_DoneCode_HeaderTooBig = -2,
|
||||
ILibWebClient_DoneCode_BodyTooBig = -3,
|
||||
};
|
||||
|
||||
enum ILibWebClient_Range_Result
|
||||
{
|
||||
ILibWebClient_Range_Result_OK = 0,
|
||||
ILibWebClient_Range_Result_INVALID_RANGE = 1,
|
||||
ILibWebClient_Range_Result_BAD_REQUEST = 2,
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ILibWebClient_ReceiveStatus_MoreDataToBeReceived = 0,
|
||||
ILibWebClient_ReceiveStatus_Complete = 1,
|
||||
ILibWebClient_ReceiveStatus_Partial = 10,
|
||||
ILibWebClient_ReceiveStatus_LastPartial = 11,
|
||||
ILibWebClient_ReceiveStatus_Connection_Established = 12
|
||||
}ILibWebClient_ReceiveStatus;
|
||||
|
||||
/*! \typedef ILibWebClient_RequestToken
|
||||
\brief The handle for a request, obtained from a call to \a ILibWebClient_PipelineRequest
|
||||
*/
|
||||
typedef void* ILibWebClient_RequestToken;
|
||||
|
||||
/*! \typedef ILibWebClient_RequestManager
|
||||
\brief An object that manages HTTP Client requests. Obtained from \a ILibCreateWebClient
|
||||
*/
|
||||
typedef void* ILibWebClient_RequestManager;
|
||||
|
||||
/*! \typedef ILibWebClient_StateObject
|
||||
\brief Handle for an HTTP Client Connection.
|
||||
*/
|
||||
typedef void* ILibWebClient_StateObject;
|
||||
|
||||
/*! \typedef ILibWebClient_OnResponse
|
||||
\brief Function Callback Pointer, dispatched to process received data
|
||||
\param WebStateObject The ILibWebClient that received a response
|
||||
\param InterruptFlag A flag indicating if this request was interrupted with a call to ILibStopChain
|
||||
\param header The packetheader object containing the HTTP headers.
|
||||
\param bodyBuffer The buffer containing the body
|
||||
\param[in,out] beginPointer The start index of the buffer referenced by \a bodyBuffer
|
||||
\param endPointer The end index of the buffer referenced by \a bodyBuffer
|
||||
\param done Flag indicating if all of the response has been received.
|
||||
\param user1
|
||||
\param user2
|
||||
\param[out] PAUSE Set to nonzero value if you do not want the system to read any more data from the network
|
||||
*/
|
||||
typedef void(*ILibWebClient_OnResponse)(ILibWebClient_StateObject WebStateObject,int InterruptFlag,struct packetheader *header,char *bodyBuffer,int *beginPointer,int endPointer,ILibWebClient_ReceiveStatus recvStatus,void *user1,void *user2,int *PAUSE);
|
||||
/*! \typedef ILibWebClient_OnSendOK
|
||||
\brief Handler for when pending send operations have completed
|
||||
\par
|
||||
<B>Note:</B> This handler will only be called after all data from any call(s) to \a ILibWebClient_StreamRequestBody
|
||||
have completed.
|
||||
\param sender The \a ILibWebClient_StateObject whos pending sends have completed
|
||||
\param user1 User1 object that was associated with this connection
|
||||
\param user2 User2 object that was associated with this connection
|
||||
*/
|
||||
typedef void(*ILibWebClient_OnSendOK)(ILibWebClient_StateObject sender, void *user1, void *user2);
|
||||
/*! \typedef ILibWebClient_OnDisconnect
|
||||
\brief Handler for when the session has disconnected
|
||||
\param sender The \a ILibWebClient_StateObject that has been disconnected
|
||||
\param request The ILibWebClient_RequestToken that represents the request that was in progress when the disconnect happened.
|
||||
*/
|
||||
typedef void(*ILibWebClient_OnDisconnect)(ILibWebClient_StateObject sender, ILibWebClient_RequestToken request);
|
||||
|
||||
#ifndef MICROSTACK_NOTLS
|
||||
typedef int(*ILibWebClient_OnSslConnection)(ILibWebClient_StateObject sender, STACK_OF(X509) *certs, struct sockaddr_in6 *address, void *user);
|
||||
typedef int(*ILibWebClient_OnHttpsConnection)(ILibWebClient_RequestToken sender, int preverify_ok, STACK_OF(X509) *certs, struct sockaddr_in6 *address);
|
||||
#endif
|
||||
|
||||
//
|
||||
// This is the number of seconds that a connection must be idle for, before it will
|
||||
// be automatically closed. Idle means there are no pending requests
|
||||
//
|
||||
/*! \def HTTP_SESSION_IDLE_TIMEOUT
|
||||
\brief This is the number of seconds that a connection must be idle for, before it will be automatically closed.
|
||||
\par
|
||||
Idle means there are no pending requests
|
||||
*/
|
||||
#define HTTP_SESSION_IDLE_TIMEOUT 10
|
||||
|
||||
/*! \def HTTP_CONNECT_RETRY_COUNT
|
||||
\brief This is the number of times, an HTTP connection will be attempted, before it fails.
|
||||
\par
|
||||
This module utilizes an exponential backoff algorithm. That is, it will retry immediately, then it will retry after 1 second, then 2, then 4, etc.
|
||||
*/
|
||||
#define HTTP_CONNECT_RETRY_COUNT 2
|
||||
|
||||
/*! \def INITIAL_BUFFER_SIZE
|
||||
\brief This initial size of the receive buffer
|
||||
*/
|
||||
#define INITIAL_BUFFER_SIZE 65535
|
||||
|
||||
extern const int ILibMemory_WebClient_RequestToken_CONTAINERSIZE;
|
||||
|
||||
ILibWebClient_RequestManager ILibCreateWebClient(int PoolSize, void *Chain);
|
||||
ILibWebClient_StateObject ILibCreateWebClientEx(ILibWebClient_OnResponse OnResponse, ILibAsyncSocket_SocketModule socketModule, void *user1, void *user2);
|
||||
|
||||
void ILibWebClient_OnBufferReAllocate(ILibAsyncSocket_SocketModule token, void *user, ptrdiff_t offSet);
|
||||
void ILibWebClient_OnData(ILibAsyncSocket_SocketModule socketModule,char* buffer,int *p_beginPointer, int endPointer,ILibAsyncSocket_OnInterrupt *InterruptPtr, void **user, int *PAUSE);
|
||||
void ILibDestroyWebClient(void *object);
|
||||
|
||||
void ILibWebClient_DestroyWebClientDataObject(ILibWebClient_StateObject token);
|
||||
struct packetheader *ILibWebClient_GetHeaderFromDataObject(ILibWebClient_StateObject token);
|
||||
|
||||
ILibWebClient_RequestToken ILibWebClient_PipelineRequestEx(
|
||||
ILibWebClient_RequestManager WebClient,
|
||||
struct sockaddr *RemoteEndpoint,
|
||||
char *headerBuffer,
|
||||
int headerBufferLength,
|
||||
int headerBuffer_FREE,
|
||||
char *bodyBuffer,
|
||||
int bodyBufferLength,
|
||||
int bodyBuffer_FREE,
|
||||
ILibWebClient_OnResponse OnResponse,
|
||||
void *user1,
|
||||
void *user2);
|
||||
|
||||
ILibWebClient_RequestToken ILibWebClient_PipelineRequest(
|
||||
ILibWebClient_RequestManager WebClient,
|
||||
struct sockaddr *RemoteEndpoint,
|
||||
struct packetheader *packet,
|
||||
ILibWebClient_OnResponse OnResponse,
|
||||
void *user1,
|
||||
void *user2);
|
||||
|
||||
ILibTransport_DoneState ILibWebClient_StreamRequestBody(
|
||||
ILibWebClient_RequestToken token,
|
||||
char *body,
|
||||
int bodyLength,
|
||||
enum ILibAsyncSocket_MemoryOwnership MemoryOwnership,
|
||||
ILibTransport_DoneState done
|
||||
);
|
||||
ILibWebClient_RequestToken ILibWebClient_PipelineStreamedRequest(
|
||||
ILibWebClient_RequestManager WebClient,
|
||||
struct sockaddr *RemoteEndpoint,
|
||||
struct packetheader *packet,
|
||||
ILibWebClient_OnResponse OnResponse,
|
||||
ILibWebClient_OnSendOK OnSendOK,
|
||||
void *user1,
|
||||
void *user2);
|
||||
|
||||
typedef enum ILibWebClient_WebSocket_DataTypes
|
||||
{
|
||||
ILibWebClient_WebSocket_DataType_UNKNOWN = 0x0,
|
||||
ILibWebClient_WebSocket_DataType_REQUEST = 0xFF,
|
||||
ILibWebClient_WebSocket_DataType_BINARY = 0x2,
|
||||
ILibWebClient_WebSocket_DataType_TEXT = 0x1
|
||||
}ILibWebClient_WebSocket_DataTypes;
|
||||
|
||||
typedef enum ILibWebClient_WebSocket_FragmentFlags
|
||||
{
|
||||
ILibWebClient_WebSocket_FragmentFlag_Incomplete = 0,
|
||||
ILibWebClient_WebSocket_FragmentFlag_Complete = 1
|
||||
}ILibWebClient_WebSocket_FragmentFlags;
|
||||
|
||||
void ILibWebClient_FinishedResponse_Server(ILibWebClient_StateObject wcdo);
|
||||
void ILibWebClient_DeleteRequests(ILibWebClient_RequestManager WebClientToken, struct sockaddr* addr);
|
||||
void ILibWebClient_Resume(ILibWebClient_StateObject wcdo);
|
||||
void ILibWebClient_Pause(ILibWebClient_StateObject wcdo);
|
||||
void ILibWebClient_Disconnect(ILibWebClient_StateObject wcdo);
|
||||
void ILibWebClient_CancelRequest(ILibWebClient_RequestToken RequestToken);
|
||||
void ILibWebClient_ResetUserObjects(ILibWebClient_StateObject webstate, void *user1, void *user2);
|
||||
ILibWebClient_RequestToken ILibWebClient_GetRequestToken_FromStateObject(ILibWebClient_StateObject WebStateObject);
|
||||
ILibWebClient_StateObject ILibWebClient_GetStateObjectFromRequestToken(ILibWebClient_RequestToken token);
|
||||
void **ILibWebClient_RequestToken_GetUserObjects(ILibWebClient_RequestToken tok);
|
||||
|
||||
void ILibWebClient_Parse_ContentRange(char *contentRange, int *Start, int *End, int *TotalLength);
|
||||
enum ILibWebClient_Range_Result ILibWebClient_Parse_Range(char *Range, long *Start, long *Length, long TotalLength);
|
||||
|
||||
void ILibWebClient_SetMaxConcurrentSessionsToServer(ILibWebClient_RequestManager WebClient, int maxConnections);
|
||||
void ILibWebClient_SetUser(ILibWebClient_RequestManager manager, void *user);
|
||||
void* ILibWebClient_GetUser(ILibWebClient_RequestManager manager);
|
||||
void* ILibWebClient_GetChain(ILibWebClient_RequestManager manager);
|
||||
void* ILibWebClient_GetChainFromWebStateObject(ILibWebClient_StateObject wcdo);
|
||||
|
||||
|
||||
typedef enum ILibWebClient_RequestToken_HTTPS
|
||||
{
|
||||
#ifndef MICROSTACK_NOTLS
|
||||
ILibWebClient_RequestToken_USE_HTTPS = 0,
|
||||
#endif
|
||||
ILibWebClient_RequestToken_USE_HTTP = 1
|
||||
}ILibWebClient_RequestToken_HTTPS;
|
||||
|
||||
#ifndef MICROSTACK_NOTLS
|
||||
void ILibWebClient_SetTLS(ILibWebClient_RequestManager manager, void *ssl_ctx, ILibWebClient_OnSslConnection OnSslConnection);
|
||||
int ILibWebClient_EnableHTTPS(ILibWebClient_RequestManager manager, struct util_cert* leafCert, X509* nonLeafCert, ILibWebClient_OnHttpsConnection OnHttpsConnection);
|
||||
void ILibWebClient_Request_SetHTTPS(ILibWebClient_RequestToken reqToken, ILibWebClient_RequestToken_HTTPS requestMode);
|
||||
#endif
|
||||
|
||||
// Added methods
|
||||
int ILibWebClient_GetLocalInterface(void* socketModule, struct sockaddr *localAddress);
|
||||
int ILibWebClient_GetRemoteInterface(void* socketModule, struct sockaddr *remoteAddress);
|
||||
int ILibWebClient_Digest_NeedAuthenticate(ILibWebClient_StateObject state);
|
||||
char* ILibWebClient_Digest_GetRealm(ILibWebClient_StateObject state);
|
||||
void ILibWebClient_GenerateAuthenticationHeader(ILibWebClient_StateObject state, ILibHTTPPacket *packet, char* username, char* password);
|
||||
#ifdef MICROSTACK_PROXY
|
||||
struct sockaddr_in6* ILibWebClient_SetProxy(ILibWebClient_RequestToken token, char *proxyHost, unsigned short proxyPort, char *username, char *password);
|
||||
void ILibWebClient_SetProxyEx(ILibWebClient_RequestToken token, struct sockaddr_in6* proxyServer, char *username, char *password);
|
||||
#endif
|
||||
|
||||
// WebSocket Methods
|
||||
typedef enum ILibWebClient_WebSocket_PingResponse
|
||||
{
|
||||
ILibWebClient_WebSocket_PingResponse_Respond = 0,
|
||||
ILibWebClient_WebSocket_PingResponse_None = 1
|
||||
}ILibWebClient_WebSocket_PingResponse;
|
||||
typedef ILibWebClient_WebSocket_PingResponse(*ILibWebClient_WebSocket_PingHandler)(ILibWebClient_StateObject state, void *user);
|
||||
typedef void(*ILibWebClient_WebSocket_PongHandler)(ILibWebClient_StateObject state, void *user);
|
||||
void ILibWebClient_AddWebSocketRequestHeaders(ILibHTTPPacket *packet, int FragmentReassemblyMaxBufferSize, ILibWebClient_OnSendOK OnSendOK);
|
||||
ILibAsyncSocket_SendStatus ILibWebClient_WebSocket_Send(ILibWebClient_StateObject state, ILibWebClient_WebSocket_DataTypes bufferType, char* buffer, int bufferLen, ILibAsyncSocket_MemoryOwnership userFree, ILibWebClient_WebSocket_FragmentFlags bufferFragment);
|
||||
void ILibWebClient_WebSocket_SetPingPongHandler(ILibWebClient_StateObject state, ILibWebClient_WebSocket_PingHandler pingHandler, ILibWebClient_WebSocket_PongHandler pongHandler, void *user);
|
||||
#define ILibWebClient_WebSocket_Ping(stateObject) ILibWebClient_WebSocket_Send((stateObject), (ILibWebClient_WebSocket_DataTypes)WEBSOCKET_OPCODE_PING, NULL, 0, ILibAsyncSocket_MemoryOwnership_STATIC, ILibWebServer_WebSocket_FragmentFlag_Complete)
|
||||
#define ILibWebClient_WebSocket_Pong(stateObject) ILibWebClient_WebSocket_Send((stateObject), (ILibWebClient_WebSocket_DataTypes)WEBSOCKET_OPCODE_PONG, NULL, 0, ILibAsyncSocket_MemoryOwnership_STATIC, ILibWebServer_WebSocket_FragmentFlag_Complete)
|
||||
|
||||
typedef void(*ILibWebClient_TimeoutHandler)(ILibWebClient_StateObject state, void *user);
|
||||
void ILibWebClient_SetTimeout(ILibWebClient_StateObject state, int timeoutSeconds, ILibWebClient_TimeoutHandler handler, void *user);
|
||||
|
||||
// OpenSSL supporting code
|
||||
#ifndef MICROSTACK_NOTLS
|
||||
X509* ILibWebClient_SslGetCert(void* socketModule);
|
||||
STACK_OF(X509)* ILibWebClient_SslGetCerts(void* socketModule);
|
||||
#endif
|
||||
|
||||
// Mesh specific code, used to store the NodeID in the web client
|
||||
char* ILibWebClient_GetCertificateHash(void* socketModule);
|
||||
char* ILibWebClient_SetCertificateHash(void* socketModule, char* ptr);
|
||||
char* ILibWebClient_GetCertificateHashEx(void* socketModule);
|
||||
|
||||
int ILibWebClient_HasAllocatedClient(ILibWebClient_RequestManager WebClient, struct sockaddr *remoteAddress);
|
||||
int ILibWebClient_GetActiveClientCount(ILibWebClient_RequestManager WebClient);
|
||||
|
||||
#ifdef UPNP_DEBUG
|
||||
char *ILibWebClient_QueryWCDO(ILibWebClient_RequestManager wcm, char *query);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
7364
microstack/ILibWebRTC.c
Normal file
7364
microstack/ILibWebRTC.c
Normal file
File diff suppressed because it is too large
Load Diff
270
microstack/ILibWebRTC.h
Normal file
270
microstack/ILibWebRTC.h
Normal file
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
Copyright 2006 - 2017 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#if !defined(___ILIBWEBRTC___) && !defined(MICROSTACK_NOTLS)
|
||||
#define ___ILIBWEBRTC___
|
||||
#include "ILibAsyncSocket.h"
|
||||
#include <openssl/ssl.h>
|
||||
|
||||
/*! \file ILibWrapperWebRTC.h
|
||||
\brief Microstack API for WebRTC Functionality
|
||||
*/
|
||||
|
||||
/*! \defgroup ILibWebRTC ILibWebRTC Module */
|
||||
/*! @{ */
|
||||
|
||||
#define ILibTransports_Raw_WebRTC 0x50
|
||||
|
||||
typedef enum ILibWebRTC_SDP_Flags
|
||||
{
|
||||
ILibWebRTC_SDP_Flags_DTLS_SERVER = 0x2
|
||||
} ILibWebRTC_SDP_Flags;
|
||||
|
||||
typedef enum ILibStun_Results
|
||||
{
|
||||
ILibStun_Results_Unknown = 0, //!< Cannot determine NAT Type
|
||||
ILibStun_Results_No_NAT = 1, //!< No NAT Detected
|
||||
ILibStun_Results_Full_Cone_NAT = 2, //!< NAT Type: FULL Cone
|
||||
ILibStun_Results_Symetric_NAT = 3, //!< NAT Type: Symmetric
|
||||
ILibStun_Results_Restricted_NAT = 4, //!< NAT Type: Address Restricted
|
||||
ILibStun_Results_Port_Restricted_NAT = 5, //!< NAT Type: Port Restricted
|
||||
ILibStun_Results_RFC5780_NOT_IMPLEMENTED = 10, //!< Server does not support RFC5780
|
||||
ILibStun_Results_Public_Interface = 11, //!< Local interface is publically accessible
|
||||
} ILibStun_Results;
|
||||
|
||||
typedef enum ILibWebRTC_TURN_ConnectFlags
|
||||
{
|
||||
ILibWebRTC_TURN_DISABLED = 0, //!< No TURN support
|
||||
ILibWebRTC_TURN_ENABLED = 1, //!< Always connect the control channel, but only use the server when necessary
|
||||
ILibWebRTC_TURN_ALWAYS_RELAY = 2 //!< Always relay all connections
|
||||
} ILibWebRTC_TURN_ConnectFlags;
|
||||
|
||||
typedef enum ILibWebRTC_DataChannel_ReliabilityModes
|
||||
{
|
||||
ILibWebRTC_DataChannel_ReliabilityMode_RELIABLE = 0x00, //!< Reliable Transport [DEFAULT]
|
||||
ILibWebRTC_DataChannel_ReliabilityMode_RELIABLE_UNORDERED = 0x80, //!< Unordered Reliable Transport
|
||||
ILibWebRTC_DataChannel_ReliabilityMode_PARTIAL_RELIABLE_REXMIT = 0x01, //!< Partial Reliable via a Max-Retransmit Attribute
|
||||
ILibWebRTC_DataChannel_ReliabilityMode_PARTIAL_RELIABLE_REXMIT_UNORDERED = 0x81, //!< Partial Reliable/Unordered via a Max-Retransmit Attribute
|
||||
ILibWebRTC_DataChannel_ReliabilityMode_PARTIAL_RELIABLE_TIMED = 0x02, //!< Partial Reliable via Timeout for Re-transmits
|
||||
ILibWebRTC_DataChannel_ReliabilityMode_PARTIAL_RELIABLE_TIMED_UNORDERED = 0x82, //!< Parital Reliable/Unordered via Timeout for Re-transmits
|
||||
}ILibWebRTC_DataChannel_ReliabilityModes;
|
||||
|
||||
#define ILibStun_SlotToChar(val) (val>26?(val+97):(val+65))
|
||||
#define ILibStun_CharToSlot(val) (val>=97?(val-97):(val-65))
|
||||
|
||||
/*! \defgroup STUN_ICE STUN & ICE Related Methods */
|
||||
/*! @{ */
|
||||
typedef void(*ILibStunClient_OnResult)(void* StunModule, ILibStun_Results Result, struct sockaddr_in* PublicIP, void *user);
|
||||
void ILibStunClient_SetOptions(void* StunModule, SSL_CTX* securityContext, char* certThumbprintSha256);
|
||||
void* ILibStunClient_Start(void *Chain, unsigned short LocalPort, ILibStunClient_OnResult OnResult);
|
||||
SSL_CTX* ILibStunClient_GetSSLCTX(void *StunModule);
|
||||
void ILibStunClient_PerformNATBehaviorDiscovery(void* StunModule, struct sockaddr_in* StunServer, void *user);
|
||||
void ILibStunClient_PerformStun(void* StunModule, struct sockaddr_in* StunServer, void *user);
|
||||
void ILibStunClient_SendData(void* StunModule, struct sockaddr* target, char* data, int datalen, enum ILibAsyncSocket_MemoryOwnership UserFree);
|
||||
int ILibStun_SetIceOffer(void* StunModule, char* iceOffer, int iceOfferLen, char** answer);
|
||||
int ILibStun_SetIceOffer2(void *StunModule, char* iceOffer, int iceOfferLen, char *username, int usernameLength, char* password, int passwordLength, char** answer);
|
||||
int ILibStun_GenerateIceOffer(void* StunModule, char** offer, char* userName, char* password);
|
||||
void ILibStun_ClearIceState(void* stunModule, int iceSlot);
|
||||
int ILibStun_GetExistingIceOfferIndex(void* stunModule, char *iceOffer, int iceOfferLen);
|
||||
/*! @} */
|
||||
|
||||
/*! \defgroup ORTC ORTC Related Methods */
|
||||
/*! @{ */
|
||||
void ILibORTC_GetLocalParameters(void *stunModule, char* username, char** password, int *passwordLength, char** certHash, int* certHashLength);
|
||||
void ILibORTC_SetRemoteParameters(void* stunModule, char *username, int usernameLen, char *password, int passwordLen, char *certHash, int certHashLen, char *localUserName);
|
||||
void ILibORTC_AddRemoteCandidate(void *stunModule, char* localUsername, struct sockaddr_in6 *candidate);
|
||||
/*! @} */
|
||||
|
||||
|
||||
/*! \defgroup General General Methods */
|
||||
/*! @{ */
|
||||
typedef enum
|
||||
{
|
||||
ILibWebRTC_DataChannel_CloseStatus_OK = 0, //!< SCTP/RECONFIG Result: OK
|
||||
ILibWebRTC_DataChannel_CloseStatus_ALREADY_PENDING = 1, //!< SCTP/RECONFIG Result: Already Pending
|
||||
ILibWebRTC_DataChannel_CloseStatus_ERROR = 254, //!< SCTP/RECONFIG Result: ERROR
|
||||
ILibWebRTC_DataChannel_CloseStatus_NOT_SUPPORTED = 255, //!< SCTP/RECONFIG Not supported by Peer
|
||||
}ILibWebRTC_DataChannel_CloseStatus;
|
||||
|
||||
int ILibWebRTC_IsDtlsInitiator(void* dtlsSession);
|
||||
void ILibWebRTC_OpenDataChannel(void *WebRTCModule, unsigned short streamId, char* channelName, int channelNameLength);
|
||||
void ILibWebRTC_CloseDataChannel_ALL(void *WebRTCModule);
|
||||
ILibWebRTC_DataChannel_CloseStatus ILibWebRTC_CloseDataChannel(void *WebRTCModule, unsigned short streamId);
|
||||
ILibWebRTC_DataChannel_CloseStatus ILibWebRTC_CloseDataChannelEx(void *WebRTCModule, unsigned short *streamIds, int streamIdsCount);
|
||||
|
||||
//! Handler for new Data Channel Associations
|
||||
/*!
|
||||
\param StunModule Local Stun/ICE Client
|
||||
\param WebRTCModule Peer Connection Session
|
||||
\param StreamId Data Channel ID
|
||||
\param ChannelName Name of the Data Channel
|
||||
\param ChannelNameLength Length of the Channel Name
|
||||
\return 0 = Respond with ACK, Non-Zero = DO NOT ACK
|
||||
*/
|
||||
typedef int(*ILibWebRTC_OnDataChannel)(void *StunModule, void* WebRTCModule, unsigned short StreamId, char* ChannelName, int ChannelNameLength);
|
||||
//! Handler for when an Associated Data Channel is closed
|
||||
/*!
|
||||
\param StunModule Local Stun/ICE Client
|
||||
\param WebRTCModule Peer Connection Session
|
||||
\param StreamId Data Channel Stream ID
|
||||
*/
|
||||
typedef void(*ILibWebRTC_OnDataChannelClosed)(void *StunModule, void* WebRTCModule, unsigned short StreamId);
|
||||
//! Handler for when a Data Channel Creation request was ACK'ed by the peer
|
||||
/*!
|
||||
\param StunModule Local Stun/ICE Client
|
||||
\param WebRTCModule Peer Connection Session
|
||||
\param StreamId Data Channel Stream ID
|
||||
*/
|
||||
typedef void(*ILibWebRTC_OnDataChannelAck)(void *StunModule, void* WebRTCModule, unsigned short StreamId);
|
||||
typedef void(*ILibWebRTC_OnOfferUpdated)(void* stunModule, char* iceOffer, int iceOfferLen);
|
||||
|
||||
void ILibWebRTC_SetCallbacks(void *StunModule, ILibWebRTC_OnDataChannel OnDataChannel, ILibWebRTC_OnDataChannelClosed OnDataChannelClosed, ILibWebRTC_OnDataChannelAck OnDataChannelAck, ILibWebRTC_OnOfferUpdated OnOfferUpdated);
|
||||
void ILibStun_DTLS_GetIceUserName(void* WebRTCModule, char* username);
|
||||
void ILibWebRTC_SetTurnServer(void* stunModule, struct sockaddr_in6* turnServer, char* username, int usernameLength, char* password, int passwordLength, ILibWebRTC_TURN_ConnectFlags turnFlags);
|
||||
void ILibWebRTC_DisableConsentFreshness(void *stunModule);
|
||||
|
||||
void ILibWebRTC_SetUserObject(void *stunModule, char* localUsername, void *userObject);
|
||||
void* ILibWebRTC_GetUserObject(void *stunModule, char* localUsername);
|
||||
void* ILibWebRTC_GetUserObjectFromDtlsSession(void *webRTCSession);
|
||||
|
||||
#ifdef _WEBRTCDEBUG
|
||||
// SCTP Instrumentation Methods/Helpers
|
||||
typedef void(*ILibSCTP_OnSenderReceiverCreditsChanged)(void *StunModule, int dtlsSessionId, int senderCredits, int receiverCredits);
|
||||
typedef void(*ILibSCTP_OnTSNChanged)(void *stunModule, int OutboundTSN, int CumulativeTSNAck);
|
||||
typedef void (*ILibSCTP_OnSCTPDebug)(void* dtlsSession, char* debugField, int data);
|
||||
void ILibSCTP_SetSenderReceiverCreditsCallback(void* stunModule, ILibSCTP_OnSenderReceiverCreditsChanged callback);
|
||||
void ILibSCTP_SetSimulatedInboundLossPercentage(void *stunModule, int lossPercentage);
|
||||
void ILibSCTP_SetTSNCallback(void *dtlsSession, ILibSCTP_OnTSNChanged tsnHandler);
|
||||
int ILibSCTP_Debug_SetDebugCallback(void *dtlsSession, char* debugFieldName, ILibSCTP_OnSCTPDebug handler);
|
||||
#endif
|
||||
/*! @} */
|
||||
|
||||
/*! \defgroup SCTP SCTP Related Methods */
|
||||
/*! @{ */
|
||||
typedef void(*ILibSCTP_OnConnect)(void *StunModule, void* SctpSession, int connected);
|
||||
typedef void(*ILibSCTP_OnData)(void* StunModule, void* SctpSession, unsigned short streamId, int pid, char* buffer, int bufferLen, void** user);
|
||||
typedef void(*ILibSCTP_OnSendOK)(void* StunModule, void* SctpSession, void* user);
|
||||
|
||||
int ILibSCTP_DoesPeerSupportFeature(void* SctpSession, int feature);
|
||||
void ILibSCTP_Pause(void* SctpSession);
|
||||
void ILibSCTP_Resume(void* SctpSession);
|
||||
|
||||
void ILibSCTP_SetCallbacks(void* StunModule, ILibSCTP_OnConnect onconnect, ILibSCTP_OnData ondata, ILibSCTP_OnSendOK onsendok);
|
||||
ILibTransport_DoneState ILibSCTP_Send(void* SctpSession, unsigned short streamId, char* data, int datalen);
|
||||
ILibTransport_DoneState ILibSCTP_SendEx(void* SctpSession, unsigned short streamId, char* data, int datalen, int dataType);
|
||||
int ILibSCTP_GetPendingBytesToSend(void* SctpSession);
|
||||
void ILibSCTP_Close(void* SctpSession);
|
||||
|
||||
void ILibSCTP_SetUser(void* SctpSession, void* user);
|
||||
void* ILibSCTP_GetUser(void* SctpSession);
|
||||
void ILibSCTP_SetUser2(void* SctpSession, void* user);
|
||||
void* ILibSCTP_GetUser2(void* SctpSession);
|
||||
void ILibSCTP_SetUser3(void* SctpSession, int user);
|
||||
int ILibSCTP_GetUser3(void* SctpSession);
|
||||
void ILibSCTP_SetUser4(void* SctpSession, int user);
|
||||
int ILibSCTP_GetUser4(void* SctpSession);
|
||||
/*! @} */
|
||||
|
||||
|
||||
// Debug
|
||||
void ILib_Stun_SendAttributeChangeRequest(void* StunModule, struct sockaddr* StunServer, int flags);
|
||||
// Note: In "ILibStunClient_Start" you can pass NULL in the LocalInterface for INADDR_ANY.
|
||||
|
||||
|
||||
/*! \defgroup TURN TURN Related Methods */
|
||||
/*! @{ */
|
||||
typedef void* ILibTURN_ClientModule;
|
||||
ILibTURN_ClientModule ILibStun_GetTurnClient(void *stunModule);
|
||||
|
||||
//! Handler for TURN Server Connection Attempts
|
||||
/*!
|
||||
\param turnModule TURN Client
|
||||
\param success 0 = FAIL, 1 = SUCCESS
|
||||
*/
|
||||
typedef void(*ILibTURN_OnConnectTurnHandler)(ILibTURN_ClientModule turnModule, int success);
|
||||
//! Handler for TURN/ALLOCATE Response
|
||||
/*!
|
||||
\param turnModule TURN Client
|
||||
\param Lifetime The cache timeout of the new allocation. If not renewed by this timeout, allocation will expire.
|
||||
\param RelayedTransportAddress The public IP Address/Port that is relayed
|
||||
*/
|
||||
typedef void(*ILibTURN_OnAllocateHandler)(ILibTURN_ClientModule turnModule, int Lifetime, struct sockaddr_in6* RelayedTransportAddress);
|
||||
typedef void(*ILibTURN_OnRefreshHandler)(ILibTURN_ClientModule turnModule, int Lifetime, void *user);
|
||||
//! Handler for TURN/PERMISSION Response
|
||||
/*!
|
||||
\param turnModule TURN Client
|
||||
\param success 0 = FAIL, 1 = SUCCESS
|
||||
\param user Custom user state object
|
||||
*/
|
||||
typedef void(*ILibTURN_OnCreatePermissionHandler)(ILibTURN_ClientModule turnModule, int success, void *user);
|
||||
//! Handler for received TURN/INDICATION
|
||||
/*!
|
||||
\param turnModule TURN Client
|
||||
\param remotePeer Origin of received Indication
|
||||
\param buffer Data received
|
||||
\param offset Data Offset Received
|
||||
\param length Data Length
|
||||
*/
|
||||
typedef void(*ILibTURN_OnDataIndicationHandler)(ILibTURN_ClientModule turnModule, struct sockaddr_in6* remotePeer, char* buffer, int offset, int length);
|
||||
//! Handler for TURN/CHANNELBIND Response
|
||||
/*!
|
||||
\param turnModule TURN Client
|
||||
\param channelNumber Channel Number
|
||||
\param success 0 = FAIL, 1 = SUCCESS
|
||||
\param user Custom user state object
|
||||
*/
|
||||
typedef void(*ILibTURN_OnCreateChannelBindingHandler)(ILibTURN_ClientModule turnModule, unsigned short channelNumber, int success, void* user);
|
||||
//! Handler for received TURN/CHANNELDATA
|
||||
/*!
|
||||
\param turnModule TURN Client
|
||||
\param channelNumber Channel Number that received data
|
||||
\param buffer Received Data
|
||||
\param offset Received Data Offset
|
||||
\param length Received Data Length
|
||||
*/
|
||||
typedef void(*ILibTURN_OnChannelDataHandler)(ILibTURN_ClientModule turnModule, unsigned short channelNumber, char* buffer, int offset, int length);
|
||||
typedef enum
|
||||
{
|
||||
ILibTURN_TransportTypes_UDP = 17, //!< TURN Transport Type: UDP
|
||||
ILibTURN_TransportTypes_TCP = 6 //!< TURN Transport Type: TCP
|
||||
}ILibTURN_TransportTypes;
|
||||
//! Create a new TURN Client Instance
|
||||
/*!
|
||||
\param chain Microstack Chain to add TURN Client to
|
||||
\param OnCennectTurn Event Handler for CONNECT Response
|
||||
\param OnAllocate Event Handler for ALLOCATE Response
|
||||
\param OnData Event Handler for INDICATION reception
|
||||
\param OnChannelData Event Handler for CHANNEL/DATA reception
|
||||
\return TURN Client Instance
|
||||
*/
|
||||
ILibTURN_ClientModule ILibTURN_CreateTurnClient(void* chain, ILibTURN_OnConnectTurnHandler OnConnectTurn, ILibTURN_OnAllocateHandler OnAllocate, ILibTURN_OnDataIndicationHandler OnData, ILibTURN_OnChannelDataHandler OnChannelData);
|
||||
void ILibTURN_SetTag(ILibTURN_ClientModule clientModule, void *tag);
|
||||
void* ILibTURN_GetTag(ILibTURN_ClientModule clientModule);
|
||||
void ILibTURN_ConnectTurnServer(ILibTURN_ClientModule turnModule, struct sockaddr_in* turnServer, char* username, int usernameLen, char* password, int passwordLen, struct sockaddr_in* proxyServer);
|
||||
void ILibTURN_Allocate(ILibTURN_ClientModule turnModule, ILibTURN_TransportTypes transportType);
|
||||
void ILibTURN_RefreshAllocation(ILibTURN_ClientModule turnModule, ILibTURN_OnRefreshHandler handler, void *user);
|
||||
int ILibTURN_CreateXORMappedAddress(struct sockaddr_in6 *endpoint, char* buffer, char* transactionID);
|
||||
void ILibTURN_GetXORMappedAddress(char* buffer, int bufferLen, char* transactionID, struct sockaddr_in6 *value);
|
||||
void ILibTURN_CreatePermission(ILibTURN_ClientModule turnModule, struct sockaddr_in6* permissions, int permissionsLength, ILibTURN_OnCreatePermissionHandler result, void* user);
|
||||
enum ILibAsyncSocket_SendStatus ILibTURN_SendIndication(ILibTURN_ClientModule turnModule, struct sockaddr_in6* remotePeer, char* buffer, int offset, int length);
|
||||
void ILibTURN_CreateChannelBinding(ILibTURN_ClientModule turnModule, unsigned short channelNumber, struct sockaddr_in6* remotePeer, ILibTURN_OnCreateChannelBindingHandler result, void* user);
|
||||
enum ILibAsyncSocket_SendStatus ILibTURN_SendChannelData(ILibTURN_ClientModule turnModule, unsigned short channelNumber, char* buffer, int offset, int length);
|
||||
int ILibTURN_IsConnectedToServer(ILibTURN_ClientModule clientModule);
|
||||
unsigned int ILibTURN_GetPendingBytesToSend(ILibTURN_ClientModule turnModule);
|
||||
/*! @} */
|
||||
/*! @} */
|
||||
|
||||
#endif
|
||||
2105
microstack/ILibWebServer.c
Normal file
2105
microstack/ILibWebServer.c
Normal file
File diff suppressed because it is too large
Load Diff
270
microstack/ILibWebServer.h
Normal file
270
microstack/ILibWebServer.h
Normal file
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
Copyright 2006 - 2017 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*! \file ILibWebServer.h
|
||||
\brief MicroStack APIs for HTTP Server functionality
|
||||
*/
|
||||
|
||||
#ifndef __ILibWebServer__
|
||||
#define __ILibWebServer__
|
||||
#include "ILibParsers.h"
|
||||
#include "ILibAsyncServerSocket.h"
|
||||
#include "ILibCrypto.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ILibTransports_WebServer 0x10
|
||||
#define ILibTransports_WebSocket 0x20
|
||||
|
||||
extern const int ILibMemory_WEBSERVERSESSION_CONTAINERSIZE;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ILibWebServer_WebSocket_DataType_UNKNOWN = 0x0,
|
||||
ILibWebServer_WebSocket_DataType_REQUEST = 0xFF,
|
||||
ILibWebServer_WebSocket_DataType_BINARY = 0x2,
|
||||
ILibWebServer_WebSocket_DataType_TEXT = 0x1
|
||||
}ILibWebServer_WebSocket_DataTypes;
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ILibWebServer_DoneFlag_NotDone = 0,
|
||||
ILibWebServer_DoneFlag_Done = 1,
|
||||
ILibWebServer_DoneFlag_Partial = 10,
|
||||
ILibWebServer_DoneFlag_LastPartial = 11
|
||||
}ILibWebServer_DoneFlag;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ILibWebServer_WebSocket_FragmentFlag_Incomplete = 0,
|
||||
ILibWebServer_WebSocket_FragmentFlag_Complete = 1
|
||||
}ILibWebServer_WebSocket_FragmentFlags;
|
||||
|
||||
|
||||
/*! \defgroup ILibWebServer ILibWebServer Module
|
||||
\{
|
||||
*/
|
||||
|
||||
typedef enum ILibWebServer_Status
|
||||
{
|
||||
ILibWebServer_ALL_DATA_SENT = 1, /*!< All of the data has already been sent */
|
||||
ILibWebServer_NOT_ALL_DATA_SENT_YET = 0, /*!< Not all of the data could be sent, but is queued to be sent as soon as possible */
|
||||
ILibWebServer_SEND_RESULTED_IN_DISCONNECT = -2, /*!< A send operation resulted in the socket being closed */
|
||||
ILibWebServer_INVALID_SESSION = -3, /*!< The specified ILibWebServer_Session was invalid */
|
||||
ILibWebServer_TRIED_TO_SEND_ON_CLOSED_SOCKET = -4, /*!< A send operation was attmepted on a closed socket */
|
||||
}ILibWebServer_Status;
|
||||
/*! \typedef ILibWebServer_ServerToken
|
||||
\brief The handle for an ILibWebServer module
|
||||
*/
|
||||
typedef void* ILibWebServer_ServerToken;
|
||||
|
||||
struct ILibWebServer_Session;
|
||||
|
||||
/*! \typedef ILibWebServer_Session_OnReceive
|
||||
\brief OnReceive Handler
|
||||
\param sender The associate \a ILibWebServer_Session object
|
||||
\param InterruptFlag boolean indicating if the underlying chain/thread is disposing
|
||||
\param header The HTTP headers that were received
|
||||
\param bodyBuffer Pointer to the HTTP body
|
||||
\param[in,out] beginPointer Starting offset of the body buffer. Advance this pointer when the data is consumed.
|
||||
\param endPointer Length of available data pointed to by \a bodyBuffer
|
||||
\param done boolean indicating if the entire packet has been received
|
||||
*/
|
||||
typedef void (*ILibWebServer_Session_OnReceive)(struct ILibWebServer_Session *sender, int InterruptFlag, struct packetheader *header, char *bodyBuffer, int *beginPointer, int endPointer, ILibWebServer_DoneFlag done);
|
||||
/*! \typedef ILibWebServer_Session_OnDisconnect
|
||||
\brief Handler for when an ILibWebServer_Session object is disconnected
|
||||
\param sender The \a ILibWebServer_Session object that was disconnected
|
||||
*/
|
||||
typedef void (*ILibWebServer_Session_OnDisconnect)(struct ILibWebServer_Session *sender);
|
||||
/*! \typedef ILibWebServer_Session_OnSendOK
|
||||
\brief Handler for when pending send operations have completed
|
||||
\par
|
||||
<B>Note:</B> This handler will only be called after all pending data from any call(s) to
|
||||
\a ILibWebServer_Send, \a ILibWebServer_Send_Raw, \a ILibWebServer_StreamBody,
|
||||
\a ILibWebServer_StreamHeader, and/or \a ILibWebServer_StreamHeader_Raw, have completed. You will need to look at the return values
|
||||
of those methods, to determine if there is any pending data that still needs to be sent. That will determine if this handler will get called.
|
||||
\param sender The \a ILibWebServer_Session that has completed sending all of the pending data
|
||||
*/
|
||||
typedef void (*ILibWebServer_Session_OnSendOK)(struct ILibWebServer_Session *sender);
|
||||
|
||||
/*! \struct ILibWebServer_Session
|
||||
\brief A structure representing the state of an HTTP Session
|
||||
*/
|
||||
typedef struct ILibWebServer_Session
|
||||
{
|
||||
ILibTransport Reserved_Transport;
|
||||
//
|
||||
// DO NOT MODIFY STRUCTURE DEFINITION ABOVE THIS COMMENT LINE (ILibTransport)
|
||||
//
|
||||
|
||||
/*! \var OnReceive
|
||||
\brief A Function Pointer that is triggered whenever data is received
|
||||
*/
|
||||
ILibWebServer_Session_OnReceive OnReceive;
|
||||
/*! \var OnDisconnect
|
||||
\brief A Function Pointer that is triggered when the session is disconnected
|
||||
*/
|
||||
ILibWebServer_Session_OnDisconnect OnDisconnect;
|
||||
/*! \var OnSendOK
|
||||
\brief A Function Pointer that is triggered when the send buffer is emptied
|
||||
*/
|
||||
ILibWebServer_Session_OnSendOK OnSendOK;
|
||||
void *Parent;
|
||||
|
||||
/*! \var User
|
||||
\brief A reserved pointer that you can use for your own use
|
||||
*/
|
||||
void *User;
|
||||
/*! \var User2
|
||||
\brief A reserved pointer that you can use for your own use
|
||||
*/
|
||||
void *User2;
|
||||
/*! \var User3
|
||||
\brief A reserved pointer that you can use for your own use
|
||||
*/
|
||||
void *User3;
|
||||
/*! \var User4
|
||||
\brief A reserved pointer that you can use for your own use
|
||||
*/
|
||||
unsigned int User4;
|
||||
unsigned int User5;
|
||||
char* CertificateHashPtr; // Points to the certificate hash (next field) if set
|
||||
char CertificateHash[32]; // Used by the Mesh to store NodeID of this session
|
||||
|
||||
char *buffer;
|
||||
int bufferLength;
|
||||
int done;
|
||||
int SessionInterrupted;
|
||||
void *ParentExtraMemory;
|
||||
}ILibWebServer_Session;
|
||||
|
||||
|
||||
void ILibWebServer_AddRef(struct ILibWebServer_Session *session);
|
||||
void ILibWebServer_Release(struct ILibWebServer_Session *session);
|
||||
|
||||
/*! \typedef ILibWebServer_Session_OnSession
|
||||
\brief New Session Handler
|
||||
\param SessionToken The new Session
|
||||
\param User The \a User object specified in \a ILibWebServer_Create
|
||||
*/
|
||||
typedef void (*ILibWebServer_Session_OnSession)(struct ILibWebServer_Session *SessionToken, void *User);
|
||||
/*! \typedef ILibWebServer_VirtualDirectory
|
||||
\brief Request Handler for a registered Virtual Directory
|
||||
\param session The session that received the request
|
||||
\param header The HTTP headers
|
||||
\param bodyBuffer Pointer to the HTTP body
|
||||
\param[in,out] beginPointer Starting index of \a bodyBuffer. Advance this pointer as data is consumed
|
||||
\param endPointer Length of available data in \a bodyBuffer
|
||||
\param done boolean indicating that the entire packet has been read
|
||||
\param user The \a user specified in \a ILibWebServer_Create
|
||||
*/
|
||||
typedef void (*ILibWebServer_VirtualDirectory)(struct ILibWebServer_Session *session, struct packetheader *header, char *bodyBuffer, int *beginPointer, int endPointer, int done, void *user);
|
||||
|
||||
#ifndef MICROSTACK_NOTLS
|
||||
typedef int(*ILibWebServer_OnHttpsConnection)(ILibWebServer_ServerToken sender, int preverify_ok, STACK_OF(X509) *certs, struct sockaddr_in6* addr);
|
||||
int ILibWebServer_EnableHTTPS(ILibWebServer_ServerToken object, struct util_cert* leafCert, X509* nonLeafCert, int requestClientCert, ILibWebServer_OnHttpsConnection onHTTPS);
|
||||
X509 *ILibWebServer_Session_SslGetCert(ILibWebServer_Session* session);
|
||||
STACK_OF(X509) *ILibWebServer_Session_SslGetCerts(ILibWebServer_Session* session);
|
||||
#ifdef MICROSTACK_TLS_DETECT
|
||||
void ILibWebServer_SetTLS(ILibWebServer_ServerToken object, void *ssl_ctx, int enableTLSDetect);
|
||||
#define ILibWebServer_IsUsingTLS(session) ILibAsyncSocket_IsUsingTls(ILibWebServer_Session_GetConnectionToken(session))
|
||||
#else
|
||||
void ILibWebServer_SetTLS(ILibWebServer_ServerToken object, void *ssl_ctx);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void ILibWebServer_SetTag(ILibWebServer_ServerToken WebServerToken, void *Tag);
|
||||
void *ILibWebServer_GetTag(ILibWebServer_ServerToken WebServerToken);
|
||||
void *ILibWebServer_Session_GetConnectionToken(ILibWebServer_Session *session);
|
||||
|
||||
ILibWebServer_ServerToken ILibWebServer_CreateEx(void *Chain, int MaxConnections, unsigned short PortNumber, int loopbackFlag, ILibWebServer_Session_OnSession OnSession, void *User);
|
||||
ILibExportMethod ILibWebServer_ServerToken ILibWebServer_CreateEx2(void *Chain, int MaxConnections, unsigned short PortNumber, int loopbackFlag, ILibWebServer_Session_OnSession OnSession, int ExtraMemorySize, void *User);
|
||||
#define ILibWebServer_Create(Chain, MaxConnections, PortNumber, OnSession, User) ILibWebServer_CreateEx(Chain, MaxConnections, PortNumber, INADDR_ANY, OnSession, User)
|
||||
#define ILibWebServer_Create2(Chain, MaxConnections, PortNumber, OnSession, ExtraMemorySize, User) ILibWebServer_CreateEx2(Chain, MaxConnections, PortNumber, INADDR_ANY, OnSession, ExtraMemorySize, User)
|
||||
|
||||
void ILibWebServer_StopListener(ILibWebServer_ServerToken server);
|
||||
void ILibWebServer_RestartListener(ILibWebServer_ServerToken server);
|
||||
|
||||
int ILibWebServer_RegisterVirtualDirectory(ILibWebServer_ServerToken WebServerToken, char *vd, int vdLength, ILibWebServer_VirtualDirectory OnVirtualDirectory, void *user);
|
||||
int ILibWebServer_UnRegisterVirtualDirectory(ILibWebServer_ServerToken WebServerToken, char *vd, int vdLength);
|
||||
|
||||
// Checks if the Web Request is uses digest authentication. Returns non zero if the request is using digest authentication
|
||||
ILibExportMethod int ILibWebServer_Digest_IsAuthenticated(struct ILibWebServer_Session *session, char* realm, int realmLen);
|
||||
// Gets the username that the client used to authenticate
|
||||
ILibExportMethod char* ILibWebServer_Digest_GetUsername(struct ILibWebServer_Session *session);
|
||||
// Validates the client's digest authentication response. Returns 0 on failure, 1 on success
|
||||
ILibExportMethod int ILibWebServer_Digest_ValidatePassword(struct ILibWebServer_Session *session, char* password, int passwordLen);
|
||||
// Send un-autorized response
|
||||
ILibExportMethod void ILibWebServer_Digest_SendUnauthorized(struct ILibWebServer_Session *session, char* realm, int realmLen, char* html, int htmllen);
|
||||
|
||||
// Returns NULL if the request was not CrossSite, otherwise returns the contents of the Origin header
|
||||
ILibExportMethod char* ILibWebServer_IsCrossSiteRequest(ILibWebServer_Session* session);
|
||||
|
||||
ILibExportMethod int ILibWebServer_UpgradeWebSocket(struct ILibWebServer_Session *session, int autoFragmentReassemblyMaxBufferSize);
|
||||
ILibExportMethod enum ILibWebServer_Status ILibWebServer_WebSocket_Send(struct ILibWebServer_Session *session, char* buffer, int bufferLen, ILibWebServer_WebSocket_DataTypes bufferType, enum ILibAsyncSocket_MemoryOwnership userFree, ILibWebServer_WebSocket_FragmentFlags fragmentStatus);
|
||||
ILibExportMethod void ILibWebServer_WebSocket_Close(struct ILibWebServer_Session *session);
|
||||
|
||||
/* Gets the WebSocket DataFrame type from the ILibWebServer_Session object 'x' */
|
||||
ILibExportMethod ILibWebServer_WebSocket_DataTypes ILibWebServer_WebSocket_GetDataType(ILibWebServer_Session *session);
|
||||
|
||||
ILibExportMethod enum ILibWebServer_Status ILibWebServer_Send(struct ILibWebServer_Session *session, struct packetheader *packet);
|
||||
ILibExportMethod enum ILibWebServer_Status ILibWebServer_Send_Raw(struct ILibWebServer_Session *session, char *buffer, int bufferSize, enum ILibAsyncSocket_MemoryOwnership userFree, ILibWebServer_DoneFlag done);
|
||||
|
||||
/*! \def ILibWebServer_Session_GetPendingBytesToSend
|
||||
\brief Returns the number of outstanding bytes to be sent
|
||||
\param session The ILibWebServer_Session object to query
|
||||
*/
|
||||
unsigned int ILibWebServer_Session_GetPendingBytesToSend(struct ILibWebServer_Session *session);
|
||||
|
||||
/*! \def ILibWebServer_Session_GetTotalBytesSent
|
||||
\brief Returns the total number of bytes sent
|
||||
\param session The ILibWebServer_Session object to query
|
||||
*/
|
||||
#define ILibWebServer_Session_GetTotalBytesSent(session) ILibAsyncServerSocket_GetTotalBytesSent(session->Reserved1,session->Reserved2)
|
||||
/*! \def ILibWebServer_Session_ResetTotalBytesSent
|
||||
\brief Resets the total bytes set counter
|
||||
\param session The ILibWebServer_Session object to query
|
||||
|
||||
*/
|
||||
#define ILibWebServer_Session_ResetTotalBytesSent(session) ILibAsyncServerSocket_ResetTotalBytesSent(session->Reserved1,session->Reserved2)
|
||||
|
||||
unsigned short ILibWebServer_GetPortNumber(ILibWebServer_ServerToken WebServerToken);
|
||||
int ILibWebServer_GetLocalInterface(struct ILibWebServer_Session *session, struct sockaddr *localAddress);
|
||||
int ILibWebServer_GetRemoteInterface(struct ILibWebServer_Session *session, struct sockaddr *remoteAddress);
|
||||
|
||||
enum ILibWebServer_Status ILibWebServer_StreamHeader(struct ILibWebServer_Session *session, struct packetheader *header);
|
||||
enum ILibWebServer_Status ILibWebServer_StreamBody(struct ILibWebServer_Session *session, char *buffer, int bufferSize, enum ILibAsyncSocket_MemoryOwnership userFree, ILibWebServer_DoneFlag done);
|
||||
|
||||
// ResponseHeaders must start with \r\n. Do not trail with \r\n
|
||||
enum ILibWebServer_Status ILibWebServer_StreamHeader_Raw(struct ILibWebServer_Session *session, int StatusCode, char *StatusData, char *ResponseHeaders, enum ILibAsyncSocket_MemoryOwnership ResponseHeaders_FREE);
|
||||
void ILibWebServer_DisconnectSession(struct ILibWebServer_Session *session);
|
||||
|
||||
ILibExportMethod void ILibWebServer_Pause(struct ILibWebServer_Session *session);
|
||||
ILibExportMethod void ILibWebServer_Resume(struct ILibWebServer_Session *session);
|
||||
|
||||
void ILibWebServer_OverrideReceiveHandler(struct ILibWebServer_Session *session, ILibWebServer_Session_OnReceive OnReceive);
|
||||
|
||||
void ILibWebServer_StreamFile(struct ILibWebServer_Session *session, FILE* pfile);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/* \} */
|
||||
#endif
|
||||
1318
microstack/ILibWrapperWebRTC.c
Normal file
1318
microstack/ILibWrapperWebRTC.c
Normal file
File diff suppressed because it is too large
Load Diff
389
microstack/ILibWrapperWebRTC.h
Normal file
389
microstack/ILibWrapperWebRTC.h
Normal file
@@ -0,0 +1,389 @@
|
||||
/*
|
||||
Copyright 2006 - 2017 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef MICROSTACK_NOTLS
|
||||
#ifndef ___ILibWrapper_WebRTC___
|
||||
#define ___ILibWrapper_WebRTC___
|
||||
|
||||
#include "ILibAsyncSocket.h"
|
||||
#include "ILibCrypto.h"
|
||||
|
||||
#define ILibWebWrapperWebRTC_ConnectionFactory_INIT_CRYPTO_LATER (void*)0x01
|
||||
/*! \file ILibWrapperWebRTC.h
|
||||
\brief Microstack API/Abstraction for WebRTC Functionality
|
||||
*/
|
||||
|
||||
/*! \defgroup ILibWrapperWebRTC ILibWrapperWebRTC Module */
|
||||
/*! @{ */
|
||||
|
||||
#define ILibTransports_WebRTC_DataChannel 0x51
|
||||
extern const int ILibMemory_WebRTC_Connection_CONTAINERSIZE;
|
||||
|
||||
/** Factory object that is used to create WebRTC Connections. */
|
||||
typedef void* ILibWrapper_WebRTC_ConnectionFactory;
|
||||
/** Object encapsulating WebRTC Peer Connections. */
|
||||
typedef void* ILibWrapper_WebRTC_Connection;
|
||||
|
||||
struct ILibWrapper_WebRTC_DataChannel;
|
||||
|
||||
//! Handler for when a remote peer has ACK'ed a Create Data Channel request
|
||||
/*
|
||||
\param dataChannel The data channel that the peer has AcK'ed
|
||||
*/
|
||||
typedef void(*ILibWrapper_WebRTC_DataChannel_OnDataChannelAck)(struct ILibWrapper_WebRTC_DataChannel* dataChannel);
|
||||
//! Handler for when data is received on a Data Channel
|
||||
/*!
|
||||
\param dataChannel The Data Channel on which data has arrived
|
||||
\param data Received data
|
||||
\param dataLen Number of bytes received
|
||||
*/
|
||||
typedef void(*ILibWrapper_WebRTC_DataChannel_OnData)(struct ILibWrapper_WebRTC_DataChannel* dataChannel, char* data, int dataLen);
|
||||
//! Raw Handler for when data is received on a Data Channel
|
||||
/*!
|
||||
\param dataChannel The Data Channel on which data has arrived
|
||||
\param data Received Data
|
||||
\param dataLen Number of bytes received
|
||||
\param dataType Kind of Data received. 51 = String, 53 = Binary, etc.
|
||||
*/
|
||||
typedef void(*ILibWrapper_WebRTC_DataChannel_OnRawData)(struct ILibWrapper_WebRTC_DataChannel* dataChannel, char* data, int dataLen, int dataType);
|
||||
//! Handler for when a data channel is closed
|
||||
/*!
|
||||
\param dataChannel The data channel that was closed
|
||||
*/
|
||||
typedef void(*ILibWrapper_WebRTC_DataChannel_OnClosed)(struct ILibWrapper_WebRTC_DataChannel* dataChannel);
|
||||
/** DataChannel abstraction used to send/receive peer-to-peer data. */
|
||||
typedef struct ILibWrapper_WebRTC_DataChannel
|
||||
{
|
||||
ILibWrapper_WebRTC_DataChannel_OnData OnBinaryData; //!< Binary Data Event Handler
|
||||
ILibWrapper_WebRTC_DataChannel_OnData OnStringData; //!< String Data Event Handler
|
||||
ILibWrapper_WebRTC_DataChannel_OnRawData OnRawData; //!< Raw Data Event Handler
|
||||
void* Chain; //!< Microstack Chain to which this object resides
|
||||
void* ReservedMemory; //!< RESERVED
|
||||
ILibTransport_SendPtr SendPtr; //!< RESERVED
|
||||
ILibTransport_ClosePtr ClosePtr; //!< RESERVED
|
||||
ILibTransport_PendingBytesToSendPtr PendingBytesPtr; //!< RESERVED
|
||||
ILibTransport_OnSendOK TransportSendOKPtr; //!< RESERVED
|
||||
unsigned int IdentifierFlags; //!< RESERVED
|
||||
/*
|
||||
*
|
||||
* DO NOT MODIFY STRUCT DEFINITION ABOVE THIS COMMENT BLOCK
|
||||
*
|
||||
*/
|
||||
unsigned short streamId; //!< Stream Identifier for this Data Channel
|
||||
char* channelName; //!< Friendly Name for this Data Channel
|
||||
|
||||
ILibWrapper_WebRTC_DataChannel_OnDataChannelAck OnAck; //!< Event triggered when Data Channel creation is ACKnowledged by the remote peer.
|
||||
ILibWrapper_WebRTC_DataChannel_OnClosed OnClosed; //!< Event triggered when the Data Channel has been closed.
|
||||
ILibWrapper_WebRTC_Connection parent; //!< The Peer Connection object that owns this data channel object
|
||||
void* userData; //!< User specified state object
|
||||
}ILibWrapper_WebRTC_DataChannel;
|
||||
|
||||
//! Handler for new ICE candidates
|
||||
/*!
|
||||
\param connection The RTC Peer Connection object that called
|
||||
\param candidate The ICE candidate
|
||||
*/
|
||||
typedef void(*ILibWrapper_WebRTC_OnConnectionCandidate)(ILibWrapper_WebRTC_Connection connection, struct sockaddr_in6* candidate);
|
||||
//! Handler for when the connection state of an SCTP session has changed
|
||||
/*!
|
||||
\param connection The RTC Peer Connection parent object
|
||||
\param connected 0 = Disconnected, 1 = Connected
|
||||
*/
|
||||
typedef void(*ILibWrapper_WebRTC_Connection_OnConnect)(ILibWrapper_WebRTC_Connection connection, int connected);
|
||||
//! Handler for when a new Data Channel was established
|
||||
/*!
|
||||
\param connection Parent RTC Peer Connection object
|
||||
\param dataChannel The Data Channel object that was created
|
||||
*/
|
||||
typedef void(*ILibWrapper_WebRTC_Connection_OnDataChannel)(ILibWrapper_WebRTC_Connection connection, ILibWrapper_WebRTC_DataChannel *dataChannel);
|
||||
//! Handler for when all the buffered send operations for a Peer Connection has been flushed
|
||||
/*!
|
||||
\param connection The RTC Peer Connection object whose send buffers have been flushed
|
||||
*/
|
||||
typedef void(*ILibWrapper_WebRTC_Connection_OnSendOK)(ILibWrapper_WebRTC_Connection connection);
|
||||
|
||||
typedef void(*ILibWrapper_WebRTC_Connection_Debug_OnEvent)(ILibWrapper_WebRTC_Connection connection, char* debugFieldName, int debugValue);
|
||||
|
||||
|
||||
/**
|
||||
* \defgroup WebRTC_ConnectionFactory WebRTC Connection Factory Methods
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
//! Creates a Factory object that can create WebRTC Connection objects.
|
||||
/*!
|
||||
\paramn chain The microstack chain to associate with this factory
|
||||
\param localPort The local UDP port to bind, for ICE/DTLS. 0 = Random
|
||||
\return A new connection factory instance
|
||||
*/
|
||||
ILibWrapper_WebRTC_ConnectionFactory ILibWrapper_WebRTC_ConnectionFactory_CreateConnectionFactory(void* chain, unsigned short localPort);
|
||||
|
||||
//! Creates a Factory object that can create WebRTC Connection objects, using the specified certs
|
||||
/*!
|
||||
\paramn chain The microstack chain to associate with this factory
|
||||
\param localPort The local UDP port to bind, for ICE/DTLS. 0 = Random
|
||||
\param tlsCert The certificate to use. ILibWebWrapperWebRTC_ConnectionFactory_INIT_CRYPTO_LATER to init crypto later
|
||||
\return A new connection factory instance
|
||||
*/
|
||||
ILibWrapper_WebRTC_ConnectionFactory ILibWrapper_WebRTC_ConnectionFactory_CreateConnectionFactory2(void* chain, unsigned short localPort, struct util_cert *tlsCert);
|
||||
|
||||
//! Initializes the crypto for a ConnectionFactory object. (Note: Only valid if ILibWebWrapperWebRTC_ConnectionFactory_INIT_CRYPTO_LATER was used previously)
|
||||
/*!
|
||||
\paramn factory The ConnectionFactory object to initialize crypto on
|
||||
\param tlsCert The certificate to use, or NULL to generate self certs
|
||||
*/
|
||||
void ILibWrapper_WebRTC_ConnectionFactory_InitCrypto(ILibWrapper_WebRTC_ConnectionFactory factory, struct util_cert *tlsCert);
|
||||
|
||||
void ILibWrapper_WebRTC_Connection_SetOnSendOK(ILibWrapper_WebRTC_Connection connection, ILibWrapper_WebRTC_Connection_OnSendOK SendOKSink);
|
||||
|
||||
SSL_CTX* ILibWrapper_WebRTC_ConnectionFactory_GetCTX(ILibWrapper_WebRTC_ConnectionFactory factory);
|
||||
void* ILibWrapper_WebRTC_Connection_GetChain(ILibWrapper_WebRTC_Connection connection);
|
||||
|
||||
void ILibWrapper_WebRTC_ConnectionFactory_SendRaw(ILibWrapper_WebRTC_ConnectionFactory factory, struct sockaddr* target, char* data, int datalen, enum ILibAsyncSocket_MemoryOwnership UserFree);
|
||||
|
||||
//! Sets the TURN server to use for all WebRTC connections.
|
||||
/*!
|
||||
\param factory ConnectionFactory to configure
|
||||
\param turnServer The TURN Server to configure
|
||||
\param username Username for the TURN Server
|
||||
\param usernameLength Length of buffer holding username
|
||||
\param password Password for the TURN Server
|
||||
\param passwordLength Length of the buffer holding the password
|
||||
\param turnSetting TURN configuration settings
|
||||
*/
|
||||
void ILibWrapper_WebRTC_ConnectionFactory_SetTurnServer(ILibWrapper_WebRTC_ConnectionFactory factory, struct sockaddr_in6* turnServer, char* username, int usernameLength, char* password, int passwordLength, ILibWebRTC_TURN_ConnectFlags turnSetting);
|
||||
|
||||
typedef void(*ILibWrapper_WebRTC_ConnectionFactory_STUNHandler)(ILibWrapper_WebRTC_ConnectionFactory sender, ILibStun_Results Result, struct sockaddr_in* PublicIP);
|
||||
void ILibWrapper_WebRTC_ConnectionFactory_PerformSTUN(ILibWrapper_WebRTC_ConnectionFactory factory, struct sockaddr_in* StunServer);
|
||||
void ILibWrapper_WebRTC_ConnectionFactory_Set_STUNHandler(ILibWrapper_WebRTC_ConnectionFactory factory, ILibWrapper_WebRTC_ConnectionFactory_STUNHandler handler);
|
||||
|
||||
//! Creates an unconnected WebRTC Connection.
|
||||
/*!
|
||||
\param factory ConnectionFactory to use to create the RTC Peer Connection
|
||||
\param OnConnectHandler Callback to trigger when the connection state has changed
|
||||
\param OnDataChannelHandler Callback to trigger when new Data Channels are established for the new RTC Peer Connection
|
||||
\param OnConnectionSendOK Callback to trigger when buffered Send data for the Peer Connection is flushed.
|
||||
\return An unconnected RTC Peer Connection
|
||||
*/
|
||||
ILibWrapper_WebRTC_Connection ILibWrapper_WebRTC_ConnectionFactory_CreateConnection(ILibWrapper_WebRTC_ConnectionFactory factory, ILibWrapper_WebRTC_Connection_OnConnect OnConnectHandler, ILibWrapper_WebRTC_Connection_OnDataChannel OnDataChannelHandler, ILibWrapper_WebRTC_Connection_OnSendOK OnConnectionSendOK);
|
||||
//! Creates an unconnected WebRTC Connection, with ILibMemory
|
||||
/*!
|
||||
\param factory ConnectionFactory to use to create the RTC Peer Connection
|
||||
\param OnConnectHandler Callback to trigger when the connection state has changed
|
||||
\param OnDataChannelHandler Callback to trigger when new Data Channels are established for the new RTC Peer Connection
|
||||
\param OnConnectionSendOK Callback to trigger when buffered Send data for the Peer Connection is flushed.
|
||||
\param extraMemorySize The size of the extra memory partition to allocation
|
||||
\return An unconnected RTC Peer Connection
|
||||
*/
|
||||
ILibWrapper_WebRTC_Connection ILibWrapper_WebRTC_ConnectionFactory_CreateConnection2(ILibWrapper_WebRTC_ConnectionFactory factory, ILibWrapper_WebRTC_Connection_OnConnect OnConnectHandler, ILibWrapper_WebRTC_Connection_OnDataChannel OnDataChannelHandler, ILibWrapper_WebRTC_Connection_OnSendOK OnConnectionSendOK, int extraMemorySize);
|
||||
|
||||
//! Fetches the associated WebRTC Connection object from the IceOfferBlock (creating a new one if it doesn't exist), and sets the remote offer
|
||||
/*!
|
||||
\param factory ConnectionFactory to use to create the RTC Peer Connection
|
||||
\param iceOfferBlock The IceOfferBlock from MeshCentral
|
||||
\param iceOfferBlockLen The length of the IceOfferBlock from MeshCentral
|
||||
\param OnConnectHandler Callback to trigger when the connection state has changed
|
||||
\param OnDataChannelHandler Callback to trigger when new Data Channels are established for the new RTC Peer Connection
|
||||
\param OnConnectionSendOK Callback to trigger when buffered Send data for the Peer Connection is flushed.
|
||||
\return An unconnected RTC Peer Connection
|
||||
*/
|
||||
ILibWrapper_WebRTC_Connection ILibWrapper_WebRTC_ConnectionFactory_CreateConnectionEx(ILibWrapper_WebRTC_ConnectionFactory factory, char *iceOfferBlock, int iceOfferBlockLen, ILibWrapper_WebRTC_Connection_OnConnect OnConnectHandler, ILibWrapper_WebRTC_Connection_OnDataChannel OnDataChannelHandler, ILibWrapper_WebRTC_Connection_OnSendOK OnConnectionSendOK);
|
||||
ILibWrapper_WebRTC_Connection ILibWrapper_WebRTC_ConnectionFactory_CreateConnectionEx2(ILibWrapper_WebRTC_ConnectionFactory factory, char *iceOfferBlock, int iceOfferBlockLen, ILibWrapper_WebRTC_Connection_OnConnect OnConnectHandler, ILibWrapper_WebRTC_Connection_OnDataChannel OnDataChannelHandler, ILibWrapper_WebRTC_Connection_OnSendOK OnConnectionSendOK, int extraMemorySize);
|
||||
|
||||
/** @}*/
|
||||
|
||||
|
||||
/**
|
||||
* \defgroup WebRTC_Connection WebRTC Connection Methods
|
||||
* @{
|
||||
*/
|
||||
int ILibWrapper_WebRTC_Connection_GetID(ILibWrapper_WebRTC_Connection connection);
|
||||
char* ILibWrapper_WebRTC_Connection_GetLocalUsername(ILibWrapper_WebRTC_Connection connection);
|
||||
|
||||
ILibTransport* ILibWrapper_WebRTC_Connection_GetRawTransport(ILibWrapper_WebRTC_Connection connection);
|
||||
//! Set the STUN Servers to use with the WebRTC Connection when gathering candidates
|
||||
/*!
|
||||
\param connection RTC Peer Connection to configure
|
||||
\param serverList Array of NULL terminated strings, where each string is a STUN Server Hostname
|
||||
\param serverLength Size of the serverList array
|
||||
*/
|
||||
void ILibWrapper_WebRTC_Connection_SetStunServers(ILibWrapper_WebRTC_Connection connection, char** serverList, int serverLength);
|
||||
|
||||
//! Queries the SCTP connection state of an RTC Peer Connection
|
||||
/*!
|
||||
\param connection The RTC Peer Connection to query
|
||||
\return 0 = Disconnected, Non-Zero = Connected
|
||||
*/
|
||||
int ILibWrapper_WebRTC_Connection_IsConnected(ILibWrapper_WebRTC_Connection connection);
|
||||
|
||||
//! Disconnects the unerlying SCTP session, if it is connected
|
||||
/*!
|
||||
\param connection The RTC Peer Connection to disconnect
|
||||
*/
|
||||
void ILibWrapper_WebRTC_Connection_Disconnect(ILibWrapper_WebRTC_Connection connection);
|
||||
|
||||
//! Gets the underlying Local ICE Offer Block
|
||||
/*!
|
||||
\param connection The RTC Peer Connection to query
|
||||
\param localOfferBlock the Local Offer Block associated with this connection
|
||||
\return The length of localOfferBlock
|
||||
*/
|
||||
int ILibWrapper_WebRTC_Connection_GetLocalOfferBlock(ILibWrapper_WebRTC_Connection connection, char **localOfferBlock);
|
||||
|
||||
//! Destroys a WebRTC Connection
|
||||
/*!
|
||||
\param connection The RTC Peer Connection to destroy
|
||||
*/
|
||||
void ILibWrapper_WebRTC_Connection_DestroyConnection(ILibWrapper_WebRTC_Connection connection);
|
||||
void ILibWrapper_WebRTC_Connection_CloseAllDataChannels(ILibWrapper_WebRTC_Connection connection);
|
||||
|
||||
//! Closes the WebRTC Data Channel.
|
||||
//! If SCTP/RECONFIG is supported, it will request to close the Data Channel before shutting down DTLS
|
||||
/*!
|
||||
\ingroup WebRTC_DataChannel
|
||||
\param dataChannel The Data Channel to close.
|
||||
*/
|
||||
void ILibWrapper_WebRTC_DataChannel_Close(ILibWrapper_WebRTC_DataChannel* dataChannel);
|
||||
|
||||
//! Creates a WebRTC Data Channel, using the next available Stream ID
|
||||
/*!
|
||||
\ingroup WebRTC_DataChannel
|
||||
\param connection The RTC Peer Connection on which to create a new data channel
|
||||
\param channelName Name of the data channel to create
|
||||
\param channelNameLen Length of channelName
|
||||
\param OnAckHandler Callback to trigger when the Remote Peer ACK's this request (Can be NULL)
|
||||
\return An un-Acknowledged Data Channel
|
||||
*/
|
||||
ILibWrapper_WebRTC_DataChannel* ILibWrapper_WebRTC_DataChannel_Create(ILibWrapper_WebRTC_Connection connection, char* channelName, int channelNameLen, ILibWrapper_WebRTC_DataChannel_OnDataChannelAck OnAckHandler);
|
||||
|
||||
//! Creates a WebRTC Data Channel, using the specified Stream ID
|
||||
/*!
|
||||
\ingroup WebRTC_DataChannel
|
||||
\param connection The RTC Peer Connection on which to create a new data channel
|
||||
\param channelName Name of the data channel to create
|
||||
\param channelNameLen Length of channelName
|
||||
\param streamId The stream identifier to associate with the Data Channel
|
||||
\param OnAckHandler Callback to trigger when the Remote Peer ACK's this request (Can be NULL)
|
||||
\return An un-Acknowledged Data Channel
|
||||
*/
|
||||
ILibWrapper_WebRTC_DataChannel* ILibWrapper_WebRTC_DataChannel_CreateEx(ILibWrapper_WebRTC_Connection connection, char* channelName, int channelNameLen, unsigned short streamId, ILibWrapper_WebRTC_DataChannel_OnDataChannelAck OnAckHandler);
|
||||
|
||||
//! Sets Custom User State Data
|
||||
/*!
|
||||
\param connection The RTC Peer Connection to set user data to
|
||||
\param user1
|
||||
\param user2
|
||||
\param user3
|
||||
*/
|
||||
void ILibWrapper_WebRTC_Connection_SetUserData(ILibWrapper_WebRTC_Connection connection, void *user1, void *user2, void *user3);
|
||||
//! Retrieves stored Custom User State Data
|
||||
/*!
|
||||
\param connection The RTC Peer Connection to fetch user data from
|
||||
\param user1
|
||||
\param user2
|
||||
\param user3
|
||||
*/
|
||||
void ILibWrapper_WebRTC_Connection_GetUserData(ILibWrapper_WebRTC_Connection connection, void **user1, void **user2, void **user3);
|
||||
int ILibWrapper_WebRTC_Connection_DoesPeerSupportUnreliableMode(ILibWrapper_WebRTC_Connection connection);
|
||||
int ILibWrapper_WebRTC_Connection_SetReliabilityMode(ILibWrapper_WebRTC_Connection connection, int isOrdered, short maxRetransmits, short maxLifetime);
|
||||
|
||||
// WebRTC Connection Management
|
||||
void ILibWrapper_WebRTC_Connection_CreateLocalParameters_ICE(ILibWrapper_WebRTC_Connection connection);
|
||||
void ILibWrapper_WebRTC_Connection_GetLocalParameters_ICE(ILibWrapper_WebRTC_Connection connection, char **username, int *usernameLen, char **password, int *passwordLen);
|
||||
void ILibWrapper_WebRTC_Connection_GetLocalParameters_DTLS(ILibWrapper_WebRTC_Connection connection, char **hash, int *hashLen);
|
||||
|
||||
//! Generate an SDP Offer (WebRTC Initiator)
|
||||
/*!
|
||||
\param connection The RTC Connection object to act as initiator
|
||||
\param onCandidates Callback triggered for each discovered ICE candidate
|
||||
\return SDP offer that contains only local candidates
|
||||
*/
|
||||
char* ILibWrapper_WebRTC_Connection_GenerateOffer(ILibWrapper_WebRTC_Connection connection, ILibWrapper_WebRTC_OnConnectionCandidate onCandidates);
|
||||
|
||||
//! Set an SDP Answer/Offer
|
||||
/*!
|
||||
\param connection The RTC Connection object to set the response to
|
||||
\param offer The SDP Answer/Offer to set
|
||||
\param offerLen The size of the buffer holding the SDP
|
||||
\param onCandidates Callback to trigger when additional ICE candidates are discovered
|
||||
\return SDP Counter Offer, containing only local candidates, which can be returned to the sender
|
||||
*/
|
||||
char* ILibWrapper_WebRTC_Connection_SetOffer(ILibWrapper_WebRTC_Connection connection, char* offer, int offerLen, ILibWrapper_WebRTC_OnConnectionCandidate onCandidates);
|
||||
|
||||
//! Generate an udpated SDP offer containing the reflexive candidate specified
|
||||
/*!
|
||||
\param connection The RTC Peer Connection that generated the reflexive candidate
|
||||
\param candidate The reflexive candidate
|
||||
\return SDP Offer containing the reflexive candidate
|
||||
*/
|
||||
char* ILibWrapper_WebRTC_Connection_AddServerReflexiveCandidateToLocalSDP(ILibWrapper_WebRTC_Connection connection, struct sockaddr_in6* candidate);
|
||||
|
||||
// Pause processing inbound data, and buffer it
|
||||
/*!
|
||||
\param connection The RTC Connection to pause
|
||||
*/
|
||||
void ILibWrapper_WebRTC_Connection_Pause(ILibWrapper_WebRTC_Connection connection);
|
||||
|
||||
//! Resume processing inbound data
|
||||
/*!
|
||||
\param connection The RTC Connection to resume
|
||||
*/
|
||||
void ILibWrapper_WebRTC_Connection_Resume(ILibWrapper_WebRTC_Connection connection);
|
||||
/** @}*/
|
||||
|
||||
/**
|
||||
* \defgroup WebRTC_DataChannel WebRTC Data Channel Methods
|
||||
* @{
|
||||
*/
|
||||
|
||||
//! Send Binary Data over the specified Data Channel
|
||||
/*!
|
||||
\param dataChannel The Data Channel to send the data on
|
||||
\param data The binary data to send
|
||||
\param dataLen The size of the binary data buffer
|
||||
\return The Send status of the send operation
|
||||
*/
|
||||
ILibTransport_DoneState ILibWrapper_WebRTC_DataChannel_Send(ILibWrapper_WebRTC_DataChannel* dataChannel, char* data, int dataLen);
|
||||
|
||||
//! Send Arbitrary Data over the specified Data Channel.
|
||||
/*!
|
||||
\param dataChannel The Data Channel to send the data on
|
||||
\param data The data to send
|
||||
\param dataLen The size of the data buffer
|
||||
\param dataType The type of data to be sent (51 = String, 53 = Binary, etc)
|
||||
\return The Send status of the send operation
|
||||
*/
|
||||
ILibTransport_DoneState ILibWrapper_WebRTC_DataChannel_SendEx(ILibWrapper_WebRTC_DataChannel* dataChannel, char* data, int dataLen, int dataType);
|
||||
|
||||
//! Send String Data over the specified Data Channel
|
||||
/*!
|
||||
\param dataChannel The Data Channel to send the data on
|
||||
\param data The string data to send
|
||||
\param dataLen The size of the string data buffer
|
||||
\return The Send status of the send operation
|
||||
*/
|
||||
ILibTransport_DoneState ILibWrapper_WebRTC_DataChannel_SendString(ILibWrapper_WebRTC_DataChannel* dataChannel, char* data, int dataLen);
|
||||
|
||||
#ifdef _WEBRTCDEBUG
|
||||
int ILibWrapper_WebRTC_Connection_Debug_Set(ILibWrapper_WebRTC_Connection connection, char* debugFieldName, ILibWrapper_WebRTC_Connection_Debug_OnEvent eventHandler);
|
||||
void ILibWrapper_WebRTC_ConnectionFactory_SetSimulatedLossPercentage(ILibWrapper_WebRTC_ConnectionFactory factory, int lossPercentage);
|
||||
#endif
|
||||
|
||||
/** @}*/
|
||||
/** @}*/
|
||||
#endif
|
||||
#endif
|
||||
310
microstack/SHA256.c
Normal file
310
microstack/SHA256.c
Normal file
@@ -0,0 +1,310 @@
|
||||
/* Functions to compute SHA256 message digest of files or memory blocks.
|
||||
according to the definition of SHA256 in FIPS 180-2.
|
||||
Copyright (C) 2007, 2011 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* Written by Ulrich Drepper <drepper@redhat.com>, 2007. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <endian.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "sha256.h"
|
||||
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
# ifdef _LIBC
|
||||
# include <byteswap.h>
|
||||
# define SWAP(n) bswap_32 (n)
|
||||
# define SWAP64(n) bswap_64 (n)
|
||||
# else
|
||||
# define SWAP(n) \
|
||||
(((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
|
||||
# define SWAP64(n) \
|
||||
(((n) << 56) \
|
||||
| (((n) & 0xff00) << 40) \
|
||||
| (((n) & 0xff0000) << 24) \
|
||||
| (((n) & 0xff000000) << 8) \
|
||||
| (((n) >> 8) & 0xff000000) \
|
||||
| (((n) >> 24) & 0xff0000) \
|
||||
| (((n) >> 40) & 0xff00) \
|
||||
| ((n) >> 56))
|
||||
# endif
|
||||
#else
|
||||
# define SWAP(n) (n)
|
||||
# define SWAP64(n) (n)
|
||||
#endif
|
||||
|
||||
|
||||
/* This array contains the bytes used to pad the buffer to the next
|
||||
64-byte boundary. (FIPS 180-2:5.1.1) */
|
||||
static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ };
|
||||
|
||||
|
||||
/* Constants for SHA256 from FIPS 180-2:4.2.2. */
|
||||
static const uint32_t K[64] =
|
||||
{
|
||||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
|
||||
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
||||
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
||||
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
||||
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
|
||||
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
|
||||
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
||||
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
||||
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
||||
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
|
||||
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
|
||||
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
||||
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
||||
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
||||
};
|
||||
|
||||
|
||||
/* Process LEN bytes of BUFFER, accumulating context into CTX.
|
||||
It is assumed that LEN % 64 == 0. */
|
||||
static void
|
||||
sha256_process_block(const void *buffer, size_t len, struct sha256_ctx *ctx)
|
||||
{
|
||||
const uint32_t *words = buffer;
|
||||
size_t nwords = len / sizeof(uint32_t);
|
||||
uint32_t a = ctx->H[0];
|
||||
uint32_t b = ctx->H[1];
|
||||
uint32_t c = ctx->H[2];
|
||||
uint32_t d = ctx->H[3];
|
||||
uint32_t e = ctx->H[4];
|
||||
uint32_t f = ctx->H[5];
|
||||
uint32_t g = ctx->H[6];
|
||||
uint32_t h = ctx->H[7];
|
||||
|
||||
/* First increment the byte count. FIPS 180-2 specifies the possible
|
||||
length of the file up to 2^64 bits. Here we only compute the
|
||||
number of bytes. */
|
||||
ctx->total64 += len;
|
||||
|
||||
/* Process all bytes in the buffer with 64 bytes in each round of
|
||||
the loop. */
|
||||
while (nwords > 0)
|
||||
{
|
||||
uint32_t W[64];
|
||||
uint32_t a_save = a;
|
||||
uint32_t b_save = b;
|
||||
uint32_t c_save = c;
|
||||
uint32_t d_save = d;
|
||||
uint32_t e_save = e;
|
||||
uint32_t f_save = f;
|
||||
uint32_t g_save = g;
|
||||
uint32_t h_save = h;
|
||||
|
||||
/* Operators defined in FIPS 180-2:4.1.2. */
|
||||
#define Ch(x, y, z) ((x & y) ^ (~x & z))
|
||||
#define Maj(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
|
||||
#define S0(x) (CYCLIC (x, 2) ^ CYCLIC (x, 13) ^ CYCLIC (x, 22))
|
||||
#define S1(x) (CYCLIC (x, 6) ^ CYCLIC (x, 11) ^ CYCLIC (x, 25))
|
||||
#define R0(x) (CYCLIC (x, 7) ^ CYCLIC (x, 18) ^ (x >> 3))
|
||||
#define R1(x) (CYCLIC (x, 17) ^ CYCLIC (x, 19) ^ (x >> 10))
|
||||
|
||||
/* It is unfortunate that C does not provide an operator for
|
||||
cyclic rotation. Hope the C compiler is smart enough. */
|
||||
#define CYCLIC(w, s) ((w >> s) | (w << (32 - s)))
|
||||
|
||||
/* Compute the message schedule according to FIPS 180-2:6.2.2 step 2. */
|
||||
for (unsigned int t = 0; t < 16; ++t)
|
||||
{
|
||||
W[t] = SWAP(*words);
|
||||
++words;
|
||||
}
|
||||
for (unsigned int t = 16; t < 64; ++t)
|
||||
W[t] = R1(W[t - 2]) + W[t - 7] + R0(W[t - 15]) + W[t - 16];
|
||||
|
||||
/* The actual computation according to FIPS 180-2:6.2.2 step 3. */
|
||||
for (unsigned int t = 0; t < 64; ++t)
|
||||
{
|
||||
uint32_t T1 = h + S1(e) + Ch(e, f, g) + K[t] + W[t];
|
||||
uint32_t T2 = S0(a) + Maj(a, b, c);
|
||||
h = g;
|
||||
g = f;
|
||||
f = e;
|
||||
e = d + T1;
|
||||
d = c;
|
||||
c = b;
|
||||
b = a;
|
||||
a = T1 + T2;
|
||||
}
|
||||
|
||||
/* Add the starting values of the context according to FIPS 180-2:6.2.2
|
||||
step 4. */
|
||||
a += a_save;
|
||||
b += b_save;
|
||||
c += c_save;
|
||||
d += d_save;
|
||||
e += e_save;
|
||||
f += f_save;
|
||||
g += g_save;
|
||||
h += h_save;
|
||||
|
||||
/* Prepare for the next round. */
|
||||
nwords -= 16;
|
||||
}
|
||||
|
||||
/* Put checksum in context given as argument. */
|
||||
ctx->H[0] = a;
|
||||
ctx->H[1] = b;
|
||||
ctx->H[2] = c;
|
||||
ctx->H[3] = d;
|
||||
ctx->H[4] = e;
|
||||
ctx->H[5] = f;
|
||||
ctx->H[6] = g;
|
||||
ctx->H[7] = h;
|
||||
}
|
||||
|
||||
|
||||
/* Initialize structure containing state of computation.
|
||||
(FIPS 180-2:5.3.2) */
|
||||
void
|
||||
__sha256_init_ctx(ctx)
|
||||
struct sha256_ctx *ctx;
|
||||
{
|
||||
ctx->H[0] = 0x6a09e667;
|
||||
ctx->H[1] = 0xbb67ae85;
|
||||
ctx->H[2] = 0x3c6ef372;
|
||||
ctx->H[3] = 0xa54ff53a;
|
||||
ctx->H[4] = 0x510e527f;
|
||||
ctx->H[5] = 0x9b05688c;
|
||||
ctx->H[6] = 0x1f83d9ab;
|
||||
ctx->H[7] = 0x5be0cd19;
|
||||
|
||||
ctx->total64 = 0;
|
||||
ctx->buflen = 0;
|
||||
}
|
||||
|
||||
|
||||
/* Process the remaining bytes in the internal buffer and the usual
|
||||
prolog according to the standard and write the result to RESBUF.
|
||||
IMPORTANT: On some systems it is required that RESBUF is correctly
|
||||
aligned for a 32 bits value. */
|
||||
void *
|
||||
__sha256_finish_ctx(ctx, resbuf)
|
||||
struct sha256_ctx *ctx;
|
||||
void *resbuf;
|
||||
{
|
||||
/* Take yet unprocessed bytes into account. */
|
||||
uint32_t bytes = ctx->buflen;
|
||||
size_t pad;
|
||||
|
||||
/* Now count remaining bytes. */
|
||||
ctx->total64 += bytes;
|
||||
|
||||
pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
|
||||
memcpy(&ctx->buffer[bytes], fillbuf, pad);
|
||||
|
||||
/* Put the 64-bit file length in *bits* at the end of the buffer. */
|
||||
#ifdef _STRING_ARCH_unaligned
|
||||
ctx->buffer64[(bytes + pad) / 8] = SWAP64(ctx->total64 << 3);
|
||||
#else
|
||||
ctx->buffer32[(bytes + pad + 4) / 4] = SWAP(ctx->total[TOTAL64_low] << 3);
|
||||
ctx->buffer32[(bytes + pad) / 4] = SWAP((ctx->total[TOTAL64_high] << 3) |
|
||||
(ctx->total[TOTAL64_low] >> 29));
|
||||
#endif
|
||||
|
||||
/* Process last bytes. */
|
||||
sha256_process_block(ctx->buffer, bytes + pad + 8, ctx);
|
||||
|
||||
/* Put result from CTX in first 32 bytes following RESBUF. */
|
||||
for (unsigned int i = 0; i < 8; ++i)
|
||||
((uint32_t *)resbuf)[i] = SWAP(ctx->H[i]);
|
||||
|
||||
return resbuf;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
__sha256_process_bytes(buffer, len, ctx)
|
||||
const void *buffer;
|
||||
size_t len;
|
||||
struct sha256_ctx *ctx;
|
||||
{
|
||||
/* When we already have some bits in our internal buffer concatenate
|
||||
both inputs first. */
|
||||
if (ctx->buflen != 0)
|
||||
{
|
||||
size_t left_over = ctx->buflen;
|
||||
size_t add = 128 - left_over > len ? len : 128 - left_over;
|
||||
|
||||
memcpy(&ctx->buffer[left_over], buffer, add);
|
||||
ctx->buflen += add;
|
||||
|
||||
if (ctx->buflen > 64)
|
||||
{
|
||||
sha256_process_block(ctx->buffer, ctx->buflen & ~63, ctx);
|
||||
|
||||
ctx->buflen &= 63;
|
||||
/* The regions in the following copy operation cannot overlap. */
|
||||
memcpy(ctx->buffer, &ctx->buffer[(left_over + add) & ~63],
|
||||
ctx->buflen);
|
||||
}
|
||||
|
||||
buffer = (const char *)buffer + add;
|
||||
len -= add;
|
||||
}
|
||||
|
||||
/* Process available complete blocks. */
|
||||
if (len >= 64)
|
||||
{
|
||||
#if !_STRING_ARCH_unaligned
|
||||
/* To check alignment gcc has an appropriate operator. Other
|
||||
compilers don't. */
|
||||
# if __GNUC__ >= 2
|
||||
# define UNALIGNED_P(p) (((uintptr_t) p) % __alignof__ (uint32_t) != 0)
|
||||
# else
|
||||
# define UNALIGNED_P(p) (((uintptr_t) p) % sizeof (uint32_t) != 0)
|
||||
# endif
|
||||
if (UNALIGNED_P(buffer))
|
||||
while (len > 64)
|
||||
{
|
||||
sha256_process_block(memcpy(ctx->buffer, buffer, 64), 64, ctx);
|
||||
buffer = (const char *)buffer + 64;
|
||||
len -= 64;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
sha256_process_block(buffer, len & ~63, ctx);
|
||||
buffer = (const char *)buffer + (len & ~63);
|
||||
len &= 63;
|
||||
}
|
||||
}
|
||||
|
||||
/* Move remaining bytes into internal buffer. */
|
||||
if (len > 0)
|
||||
{
|
||||
size_t left_over = ctx->buflen;
|
||||
|
||||
memcpy(&ctx->buffer[left_over], buffer, len);
|
||||
left_over += len;
|
||||
if (left_over >= 64)
|
||||
{
|
||||
sha256_process_block(ctx->buffer, 64, ctx);
|
||||
left_over -= 64;
|
||||
memcpy(ctx->buffer, &ctx->buffer[64], left_over);
|
||||
}
|
||||
ctx->buflen = left_over;
|
||||
}
|
||||
}
|
||||
65
microstack/SHA256.h
Normal file
65
microstack/SHA256.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/* Declaration of functions and data types used for SHA256 sum computing
|
||||
library functions.
|
||||
Copyright (C) 2007, 2011 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _SHA256_H
|
||||
#define _SHA256_H 1
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <endian.h>
|
||||
|
||||
|
||||
/* Structure to save state of computation between the single steps. */
|
||||
struct sha256_ctx
|
||||
{
|
||||
uint32_t H[8];
|
||||
|
||||
union
|
||||
{
|
||||
uint64_t total64;
|
||||
#define TOTAL64_low (1 - (BYTE_ORDER == LITTLE_ENDIAN))
|
||||
#define TOTAL64_high (BYTE_ORDER == LITTLE_ENDIAN)
|
||||
uint32_t total[2];
|
||||
};
|
||||
uint32_t buflen;
|
||||
union
|
||||
{
|
||||
char buffer[128];
|
||||
uint32_t buffer32[32];
|
||||
uint64_t buffer64[16];
|
||||
};
|
||||
};
|
||||
|
||||
/* Initialize structure containing state of computation.
|
||||
(FIPS 180-2: 5.3.2) */
|
||||
extern void __sha256_init_ctx(struct sha256_ctx *ctx) __THROW;
|
||||
|
||||
/* Starting with the result of former calls of this function (or the
|
||||
initialization function update the context for the next LEN bytes
|
||||
starting at BUFFER.
|
||||
It is NOT required that LEN is a multiple of 64. */
|
||||
extern void __sha256_process_bytes(const void *buffer, size_t len,
|
||||
struct sha256_ctx *ctx) __THROW;
|
||||
|
||||
/* Process the remaining bytes in the buffer and put result from CTX
|
||||
in first 32 bytes following RESBUF.
|
||||
IMPORTANT: On some systems it is required that RESBUF is correctly
|
||||
aligned for a 32 bits value. */
|
||||
extern void *__sha256_finish_ctx(struct sha256_ctx *ctx, void *resbuf)
|
||||
__THROW;
|
||||
|
||||
#endif /* sha256.h */
|
||||
296
microstack/md5.c
Normal file
296
microstack/md5.c
Normal file
@@ -0,0 +1,296 @@
|
||||
/*
|
||||
* This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
|
||||
* MD5 Message-Digest Algorithm (RFC 1321).
|
||||
*
|
||||
* Homepage:
|
||||
* http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
|
||||
*
|
||||
* Author:
|
||||
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
|
||||
*
|
||||
* This software was written by Alexander Peslyak in 2001. No copyright is
|
||||
* claimed, and the software is hereby placed in the public domain.
|
||||
* In case this attempt to disclaim copyright and place the software in the
|
||||
* public domain is deemed null and void, then the software is
|
||||
* Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
|
||||
* general public under the following terms:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted.
|
||||
*
|
||||
* There's ABSOLUTELY NO WARRANTY, express or implied.
|
||||
*
|
||||
* (This is a heavily cut-down "BSD license".)
|
||||
*
|
||||
* This differs from Colin Plumb's older public domain implementation in that
|
||||
* no exactly 32-bit integer data type is required (any 32-bit or wider
|
||||
* unsigned integer data type will do), there's no compile-time endianness
|
||||
* configuration, and the function prototypes match OpenSSL's. No code from
|
||||
* Colin Plumb's implementation has been reused; this comment merely compares
|
||||
* the properties of the two independent implementations.
|
||||
*
|
||||
* The primary goals of this implementation are portability and ease of use.
|
||||
* It is meant to be fast, but not as fast as possible. Some known
|
||||
* optimizations are not included to reduce source code size and avoid
|
||||
* compile-time configuration.
|
||||
*/
|
||||
|
||||
#if !defined(HAVE_OPENSSL) && defined(MICROSTACK_NOTLS)
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "md5.h"
|
||||
|
||||
/*
|
||||
* The basic MD5 functions.
|
||||
*
|
||||
* F and G are optimized compared to their RFC 1321 definitions for
|
||||
* architectures that lack an AND-NOT instruction, just like in Colin Plumb's
|
||||
* implementation.
|
||||
*/
|
||||
#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
|
||||
#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
|
||||
#define H(x, y, z) (((x) ^ (y)) ^ (z))
|
||||
#define H2(x, y, z) ((x) ^ ((y) ^ (z)))
|
||||
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
|
||||
|
||||
/*
|
||||
* The MD5 transformation for all four rounds.
|
||||
*/
|
||||
#define STEP(f, a, b, c, d, x, t, s) \
|
||||
(a) += f((b), (c), (d)) + (x) + (t); \
|
||||
(a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
|
||||
(a) += (b);
|
||||
|
||||
/*
|
||||
* SET reads 4 input bytes in little-endian byte order and stores them
|
||||
* in a properly aligned word in host byte order.
|
||||
*
|
||||
* The check for little-endian architectures that tolerate unaligned
|
||||
* memory accesses is just an optimization. Nothing will break if it
|
||||
* doesn't work.
|
||||
*/
|
||||
#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
|
||||
#define SET(n) \
|
||||
(*(MD5_u32plus *)&ptr[(n) * 4])
|
||||
#define GET(n) \
|
||||
SET(n)
|
||||
#else
|
||||
#define SET(n) \
|
||||
(ctx->block[(n)] = \
|
||||
(MD5_u32plus)ptr[(n) * 4] | \
|
||||
((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \
|
||||
((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \
|
||||
((MD5_u32plus)ptr[(n) * 4 + 3] << 24))
|
||||
#define GET(n) \
|
||||
(ctx->block[(n)])
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This processes one or more 64-byte data blocks, but does NOT update
|
||||
* the bit counters. There are no alignment requirements.
|
||||
*/
|
||||
static const void *body(MD5_CTX *ctx, const void *data, unsigned long size)
|
||||
{
|
||||
const unsigned char *ptr;
|
||||
MD5_u32plus a, b, c, d;
|
||||
MD5_u32plus saved_a, saved_b, saved_c, saved_d;
|
||||
|
||||
ptr = (const unsigned char *)data;
|
||||
|
||||
a = ctx->a;
|
||||
b = ctx->b;
|
||||
c = ctx->c;
|
||||
d = ctx->d;
|
||||
|
||||
do {
|
||||
saved_a = a;
|
||||
saved_b = b;
|
||||
saved_c = c;
|
||||
saved_d = d;
|
||||
|
||||
/* Round 1 */
|
||||
STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
|
||||
STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
|
||||
STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
|
||||
STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
|
||||
STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
|
||||
STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
|
||||
STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
|
||||
STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
|
||||
STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
|
||||
STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
|
||||
STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
|
||||
STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
|
||||
STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
|
||||
STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
|
||||
STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
|
||||
STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
|
||||
|
||||
/* Round 2 */
|
||||
STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
|
||||
STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
|
||||
STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
|
||||
STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
|
||||
STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
|
||||
STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
|
||||
STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
|
||||
STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
|
||||
STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
|
||||
STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
|
||||
STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
|
||||
STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
|
||||
STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
|
||||
STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
|
||||
STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
|
||||
STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
|
||||
|
||||
/* Round 3 */
|
||||
STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
|
||||
STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11)
|
||||
STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
|
||||
STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23)
|
||||
STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
|
||||
STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11)
|
||||
STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
|
||||
STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23)
|
||||
STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
|
||||
STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11)
|
||||
STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
|
||||
STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23)
|
||||
STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
|
||||
STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11)
|
||||
STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
|
||||
STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23)
|
||||
|
||||
/* Round 4 */
|
||||
STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
|
||||
STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
|
||||
STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
|
||||
STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
|
||||
STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
|
||||
STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
|
||||
STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
|
||||
STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
|
||||
STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
|
||||
STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
|
||||
STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
|
||||
STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
|
||||
STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
|
||||
STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
|
||||
STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
|
||||
STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
|
||||
|
||||
a += saved_a;
|
||||
b += saved_b;
|
||||
c += saved_c;
|
||||
d += saved_d;
|
||||
|
||||
ptr += 64;
|
||||
} while (size -= 64);
|
||||
|
||||
ctx->a = a;
|
||||
ctx->b = b;
|
||||
ctx->c = c;
|
||||
ctx->d = d;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void MD5_Init(MD5_CTX *ctx)
|
||||
{
|
||||
ctx->a = 0x67452301;
|
||||
ctx->b = 0xefcdab89;
|
||||
ctx->c = 0x98badcfe;
|
||||
ctx->d = 0x10325476;
|
||||
|
||||
ctx->lo = 0;
|
||||
ctx->hi = 0;
|
||||
}
|
||||
|
||||
void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size)
|
||||
{
|
||||
MD5_u32plus saved_lo;
|
||||
unsigned long used, available;
|
||||
|
||||
saved_lo = ctx->lo;
|
||||
if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
|
||||
ctx->hi++;
|
||||
ctx->hi += size >> 29;
|
||||
|
||||
used = saved_lo & 0x3f;
|
||||
|
||||
if (used) {
|
||||
available = 64 - used;
|
||||
|
||||
if (size < available) {
|
||||
memcpy(&ctx->buffer[used], data, size);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(&ctx->buffer[used], data, available);
|
||||
data = (const unsigned char *)data + available;
|
||||
size -= available;
|
||||
body(ctx, ctx->buffer, 64);
|
||||
}
|
||||
|
||||
if (size >= 64) {
|
||||
data = body(ctx, data, size & ~(unsigned long)0x3f);
|
||||
size &= 0x3f;
|
||||
}
|
||||
|
||||
memcpy(ctx->buffer, data, size);
|
||||
}
|
||||
|
||||
void MD5_Final(unsigned char *result, MD5_CTX *ctx)
|
||||
{
|
||||
unsigned long used, available;
|
||||
|
||||
used = ctx->lo & 0x3f;
|
||||
|
||||
ctx->buffer[used++] = 0x80;
|
||||
|
||||
available = 64 - used;
|
||||
|
||||
if (available < 8) {
|
||||
memset(&ctx->buffer[used], 0, available);
|
||||
body(ctx, ctx->buffer, 64);
|
||||
used = 0;
|
||||
available = 64;
|
||||
}
|
||||
|
||||
memset(&ctx->buffer[used], 0, available - 8);
|
||||
|
||||
ctx->lo <<= 3;
|
||||
ctx->buffer[56] = (unsigned char)(ctx->lo);
|
||||
ctx->buffer[57] = (unsigned char)(ctx->lo >> 8);
|
||||
ctx->buffer[58] = (unsigned char)(ctx->lo >> 16);
|
||||
ctx->buffer[59] = (unsigned char)(ctx->lo >> 24);
|
||||
ctx->buffer[60] = (unsigned char)(ctx->hi);
|
||||
ctx->buffer[61] = (unsigned char)(ctx->hi >> 8);
|
||||
ctx->buffer[62] = (unsigned char)(ctx->hi >> 16);
|
||||
ctx->buffer[63] = (unsigned char)(ctx->hi >> 24);
|
||||
|
||||
body(ctx, ctx->buffer, 64);
|
||||
|
||||
result[0] = (unsigned char)(ctx->a);
|
||||
result[1] = (unsigned char)(ctx->a >> 8);
|
||||
result[2] = (unsigned char)(ctx->a >> 16);
|
||||
result[3] = (unsigned char)(ctx->a >> 24);
|
||||
result[4] = (unsigned char)(ctx->b);
|
||||
result[5] = (unsigned char)(ctx->b >> 8);
|
||||
result[6] = (unsigned char)(ctx->b >> 16);
|
||||
result[7] = (unsigned char)(ctx->b >> 24);
|
||||
result[8] = (unsigned char)(ctx->c);
|
||||
result[9] = (unsigned char)(ctx->c >> 8);
|
||||
result[10] = (unsigned char)(ctx->c >> 16);
|
||||
result[11] = (unsigned char)(ctx->c >> 24);
|
||||
result[12] = (unsigned char)(ctx->d);
|
||||
result[13] = (unsigned char)(ctx->d >> 8);
|
||||
result[14] = (unsigned char)(ctx->d >> 16);
|
||||
result[15] = (unsigned char)(ctx->d >> 24);
|
||||
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
}
|
||||
|
||||
#endif
|
||||
45
microstack/md5.h
Normal file
45
microstack/md5.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
|
||||
* MD5 Message-Digest Algorithm (RFC 1321).
|
||||
*
|
||||
* Homepage:
|
||||
* http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
|
||||
*
|
||||
* Author:
|
||||
* Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
|
||||
*
|
||||
* This software was written by Alexander Peslyak in 2001. No copyright is
|
||||
* claimed, and the software is hereby placed in the public domain.
|
||||
* In case this attempt to disclaim copyright and place the software in the
|
||||
* public domain is deemed null and void, then the software is
|
||||
* Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
|
||||
* general public under the following terms:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted.
|
||||
*
|
||||
* There's ABSOLUTELY NO WARRANTY, express or implied.
|
||||
*
|
||||
* See md5.c for more information.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_OPENSSL
|
||||
#include <openssl/md5.h>
|
||||
#elif !defined(_MD5_H)
|
||||
#define _MD5_H
|
||||
|
||||
/* Any 32-bit or wider unsigned integer data type will do */
|
||||
typedef unsigned int MD5_u32plus;
|
||||
|
||||
typedef struct {
|
||||
MD5_u32plus lo, hi;
|
||||
MD5_u32plus a, b, c, d;
|
||||
unsigned char buffer[64];
|
||||
MD5_u32plus block[16];
|
||||
} MD5_CTX;
|
||||
|
||||
extern void MD5_Init(MD5_CTX *ctx);
|
||||
extern void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size);
|
||||
extern void MD5_Final(unsigned char *result, MD5_CTX *ctx);
|
||||
|
||||
#endif
|
||||
325
microstack/sha1.c
Normal file
325
microstack/sha1.c
Normal file
@@ -0,0 +1,325 @@
|
||||
/* This code is public-domain - it is based on libcrypt
|
||||
* placed in the public domain by Wei Dai and other contributors.
|
||||
*
|
||||
* Obtained from: http://oauth.googlecode.com/svn/code/c/liboauth/src/sha1.c
|
||||
* Source Project: http://code.google.com/p/oauth/
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef MICROSTACK_NOTLS
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
# define SHA_BIG_ENDIAN
|
||||
#elif defined __LITTLE_ENDIAN__
|
||||
/* override */
|
||||
#elif defined __BYTE_ORDER
|
||||
# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
# define SHA_BIG_ENDIAN
|
||||
# endif
|
||||
//#else // ! defined __LITTLE_ENDIAN__
|
||||
//# include <endian.h> // machine/endian.h
|
||||
//# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
//# define SHA_BIG_ENDIAN
|
||||
//# endif
|
||||
#endif
|
||||
|
||||
|
||||
/* header */
|
||||
|
||||
#define HASH_LENGTH 20
|
||||
#define BLOCK_LENGTH 64
|
||||
|
||||
#include "sha1.h"
|
||||
|
||||
/* public API - prototypes - TODO: doxygen*/
|
||||
|
||||
|
||||
/**
|
||||
*/
|
||||
void sha1_writebyte(sha1nfo *s, uint8_t data);
|
||||
/**
|
||||
*/
|
||||
void sha1_write(sha1nfo *s, const char *data, size_t len);
|
||||
/**
|
||||
*/
|
||||
uint8_t* sha1_result(sha1nfo *s);
|
||||
/**
|
||||
*/
|
||||
void sha1_initHmac(sha1nfo *s, const uint8_t* key, int keyLength);
|
||||
/**
|
||||
*/
|
||||
uint8_t* sha1_resultHmac(sha1nfo *s);
|
||||
|
||||
|
||||
/* code */
|
||||
#define SHA1_K0 0x5a827999
|
||||
#define SHA1_K20 0x6ed9eba1
|
||||
#define SHA1_K40 0x8f1bbcdc
|
||||
#define SHA1_K60 0xca62c1d6
|
||||
|
||||
void SHA1_Init(sha1nfo *s)
|
||||
{
|
||||
s->state[0] = 0x67452301;
|
||||
s->state[1] = 0xefcdab89;
|
||||
s->state[2] = 0x98badcfe;
|
||||
s->state[3] = 0x10325476;
|
||||
s->state[4] = 0xc3d2e1f0;
|
||||
s->byteCount = 0;
|
||||
s->bufferOffset = 0;
|
||||
}
|
||||
|
||||
uint32_t sha1_rol32(uint32_t number, uint8_t bits) {
|
||||
return ((number << bits) | (number >> (32-bits)));
|
||||
}
|
||||
|
||||
void sha1_hashBlock(sha1nfo *s) {
|
||||
uint8_t i;
|
||||
uint32_t a,b,c,d,e,t;
|
||||
|
||||
a=s->state[0];
|
||||
b=s->state[1];
|
||||
c=s->state[2];
|
||||
d=s->state[3];
|
||||
e=s->state[4];
|
||||
for (i=0; i<80; i++) {
|
||||
if (i>=16) {
|
||||
t = s->buffer[(i+13)&15] ^ s->buffer[(i+8)&15] ^ s->buffer[(i+2)&15] ^ s->buffer[i&15];
|
||||
s->buffer[i&15] = sha1_rol32(t,1);
|
||||
}
|
||||
if (i<20) {
|
||||
t = (d ^ (b & (c ^ d))) + SHA1_K0;
|
||||
} else if (i<40) {
|
||||
t = (b ^ c ^ d) + SHA1_K20;
|
||||
} else if (i<60) {
|
||||
t = ((b & c) | (d & (b | c))) + SHA1_K40;
|
||||
} else {
|
||||
t = (b ^ c ^ d) + SHA1_K60;
|
||||
}
|
||||
t+=sha1_rol32(a,5) + e + s->buffer[i&15];
|
||||
e=d;
|
||||
d=c;
|
||||
c=sha1_rol32(b,30);
|
||||
b=a;
|
||||
a=t;
|
||||
}
|
||||
s->state[0] += a;
|
||||
s->state[1] += b;
|
||||
s->state[2] += c;
|
||||
s->state[3] += d;
|
||||
s->state[4] += e;
|
||||
}
|
||||
|
||||
void sha1_addUncounted(sha1nfo *s, uint8_t data) {
|
||||
uint8_t * const b = (uint8_t*) s->buffer;
|
||||
#ifdef SHA_BIG_ENDIAN
|
||||
b[s->bufferOffset] = data;
|
||||
#else
|
||||
b[s->bufferOffset ^ 3] = data;
|
||||
#endif
|
||||
s->bufferOffset++;
|
||||
if (s->bufferOffset == BLOCK_LENGTH) {
|
||||
sha1_hashBlock(s);
|
||||
s->bufferOffset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void sha1_writebyte(sha1nfo *s, uint8_t data) {
|
||||
++s->byteCount;
|
||||
sha1_addUncounted(s, data);
|
||||
}
|
||||
|
||||
void sha1_write(sha1nfo *s, const char *data, size_t len) {
|
||||
for (;len--;) sha1_writebyte(s, (uint8_t) *data++);
|
||||
}
|
||||
|
||||
void sha1_pad(sha1nfo *s) {
|
||||
// Implement SHA-1 padding (fips180-2 §5.1.1)
|
||||
|
||||
// Pad with 0x80 followed by 0x00 until the end of the block
|
||||
sha1_addUncounted(s, 0x80);
|
||||
while (s->bufferOffset != 56) sha1_addUncounted(s, 0x00);
|
||||
|
||||
// Append length in the last 8 bytes
|
||||
sha1_addUncounted(s, 0); // We're only using 32 bit lengths
|
||||
sha1_addUncounted(s, 0); // But SHA-1 supports 64 bit lengths
|
||||
sha1_addUncounted(s, 0); // So zero pad the top bits
|
||||
sha1_addUncounted(s, s->byteCount >> 29); // Shifting to multiply by 8
|
||||
sha1_addUncounted(s, s->byteCount >> 21); // as SHA-1 supports bitstreams as well as
|
||||
sha1_addUncounted(s, s->byteCount >> 13); // byte.
|
||||
sha1_addUncounted(s, s->byteCount >> 5);
|
||||
sha1_addUncounted(s, s->byteCount << 3);
|
||||
}
|
||||
|
||||
uint8_t* sha1_result(sha1nfo *s) {
|
||||
int i;
|
||||
// Pad to complete the last block
|
||||
sha1_pad(s);
|
||||
|
||||
#ifndef SHA_BIG_ENDIAN
|
||||
// Swap byte order back
|
||||
|
||||
for (i=0; i<5; i++) {
|
||||
s->state[i]=
|
||||
(((s->state[i])<<24)& 0xff000000)
|
||||
| (((s->state[i])<<8) & 0x00ff0000)
|
||||
| (((s->state[i])>>8) & 0x0000ff00)
|
||||
| (((s->state[i])>>24)& 0x000000ff);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Return pointer to hash (20 characters)
|
||||
return (uint8_t*) s->state;
|
||||
}
|
||||
|
||||
#define HMAC_IPAD 0x36
|
||||
#define HMAC_OPAD 0x5c
|
||||
|
||||
void sha1_initHmac(sha1nfo *s, const uint8_t* key, int keyLength) {
|
||||
uint8_t i;
|
||||
memset(s->keyBuffer, 0, BLOCK_LENGTH);
|
||||
if (keyLength > BLOCK_LENGTH) {
|
||||
// Hash long keys
|
||||
SHA1_Init(s);
|
||||
for (;keyLength--;) sha1_writebyte(s, *key++);
|
||||
memcpy(s->keyBuffer, sha1_result(s), HASH_LENGTH);
|
||||
} else {
|
||||
// Block length keys are used as is
|
||||
memcpy(s->keyBuffer, key, keyLength);
|
||||
}
|
||||
// Start inner hash
|
||||
SHA1_Init(s);
|
||||
for (i=0; i<BLOCK_LENGTH; i++) {
|
||||
sha1_writebyte(s, s->keyBuffer[i] ^ HMAC_IPAD);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t* sha1_resultHmac(sha1nfo *s) {
|
||||
uint8_t i;
|
||||
// Complete inner hash
|
||||
memcpy(s->innerHash,sha1_result(s),HASH_LENGTH);
|
||||
// Calculate outer hash
|
||||
SHA1_Init(s);
|
||||
for (i=0; i<BLOCK_LENGTH; i++) sha1_writebyte(s, s->keyBuffer[i] ^ HMAC_OPAD);
|
||||
for (i=0; i<HASH_LENGTH; i++) sha1_writebyte(s, s->innerHash[i]);
|
||||
return sha1_result(s);
|
||||
}
|
||||
|
||||
/* self-test */
|
||||
|
||||
#if SHA1TEST
|
||||
#include <stdio.h>
|
||||
|
||||
uint8_t hmacKey1[]={
|
||||
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
|
||||
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
|
||||
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
|
||||
0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f
|
||||
};
|
||||
uint8_t hmacKey2[]={
|
||||
0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
|
||||
0x40,0x41,0x42,0x43
|
||||
};
|
||||
uint8_t hmacKey3[]={
|
||||
0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,
|
||||
0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
|
||||
0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
|
||||
0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
|
||||
0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
|
||||
0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
|
||||
0xb0,0xb1,0xb2,0xb3
|
||||
};
|
||||
uint8_t hmacKey4[]={
|
||||
0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
|
||||
0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
|
||||
0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
|
||||
0xa0
|
||||
};
|
||||
|
||||
void printHash(uint8_t* hash) {
|
||||
int i;
|
||||
for (i=0; i<20; i++) {
|
||||
printf("%02x", hash[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
int main (int argc, char **argv) {
|
||||
uint32_t a;
|
||||
sha1nfo s;
|
||||
|
||||
// SHA tests
|
||||
printf("Test: FIPS 180-2 C.1 and RFC3174 7.3 TEST1\n");
|
||||
printf("Expect:a9993e364706816aba3e25717850c26c9cd0d89d\n");
|
||||
printf("Result:");
|
||||
sha1_init(&s);
|
||||
sha1_write(&s, "abc", 3);
|
||||
printHash(sha1_result(&s));
|
||||
printf("\n\n");
|
||||
|
||||
printf("Test: FIPS 180-2 C.2 and RFC3174 7.3 TEST2\n");
|
||||
printf("Expect:84983e441c3bd26ebaae4aa1f95129e5e54670f1\n");
|
||||
printf("Result:");
|
||||
sha1_init(&s);
|
||||
sha1_write(&s, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56);
|
||||
printHash(sha1_result(&s));
|
||||
printf("\n\n");
|
||||
|
||||
printf("Test: RFC3174 7.3 TEST4\n");
|
||||
printf("Expect:dea356a2cddd90c7a7ecedc5ebb563934f460452\n");
|
||||
printf("Result:");
|
||||
sha1_init(&s);
|
||||
for (a=0; a<80; a++) sha1_write(&s, "01234567", 8);
|
||||
printHash(sha1_result(&s));
|
||||
printf("\n\n");
|
||||
|
||||
// HMAC tests
|
||||
printf("Test: FIPS 198a A.1\n");
|
||||
printf("Expect:4f4ca3d5d68ba7cc0a1208c9c61e9c5da0403c0a\n");
|
||||
printf("Result:");
|
||||
sha1_initHmac(&s, hmacKey1, 64);
|
||||
sha1_write(&s, "Sample #1",9);
|
||||
printHash(sha1_resultHmac(&s));
|
||||
printf("\n\n");
|
||||
|
||||
printf("Test: FIPS 198a A.2\n");
|
||||
printf("Expect:0922d3405faa3d194f82a45830737d5cc6c75d24\n");
|
||||
printf("Result:");
|
||||
sha1_initHmac(&s, hmacKey2, 20);
|
||||
sha1_write(&s, "Sample #2", 9);
|
||||
printHash(sha1_resultHmac(&s));
|
||||
printf("\n\n");
|
||||
|
||||
printf("Test: FIPS 198a A.3\n");
|
||||
printf("Expect:bcf41eab8bb2d802f3d05caf7cb092ecf8d1a3aa\n");
|
||||
printf("Result:");
|
||||
sha1_initHmac(&s, hmacKey3,100);
|
||||
sha1_write(&s, "Sample #3", 9);
|
||||
printHash(sha1_resultHmac(&s));
|
||||
printf("\n\n");
|
||||
|
||||
printf("Test: FIPS 198a A.4\n");
|
||||
printf("Expect:9ea886efe268dbecce420c7524df32e0751a2a26\n");
|
||||
printf("Result:");
|
||||
sha1_initHmac(&s, hmacKey4,49);
|
||||
sha1_write(&s, "Sample #4", 9);
|
||||
printHash(sha1_resultHmac(&s));
|
||||
printf("\n\n");
|
||||
|
||||
// Long tests
|
||||
printf("Test: FIPS 180-2 C.3 and RFC3174 7.3 TEST3\n");
|
||||
printf("Expect:34aa973cd4c4daa4f61eeb2bdbad27316534016f\n");
|
||||
printf("Result:");
|
||||
sha1_init(&s);
|
||||
for (a=0; a<1000000; a++) sha1_writebyte(&s, 'a');
|
||||
printHash(sha1_result(&s));
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* self-test */
|
||||
#endif
|
||||
43
microstack/sha1.h
Normal file
43
microstack/sha1.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
Copyright 2015 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __SHA1H__
|
||||
#define __SHA1H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define HASH_LENGTH 20
|
||||
#define BLOCK_LENGTH 64
|
||||
|
||||
typedef struct sha1nfo {
|
||||
uint32_t buffer[BLOCK_LENGTH / 4];
|
||||
uint32_t state[HASH_LENGTH / 4];
|
||||
uint32_t byteCount;
|
||||
uint8_t bufferOffset;
|
||||
uint8_t keyBuffer[BLOCK_LENGTH];
|
||||
uint8_t innerHash[HASH_LENGTH];
|
||||
} sha1nfo;
|
||||
typedef sha1nfo SHA_CTX;
|
||||
|
||||
void sha1_write(sha1nfo *s, const char *data, size_t len);
|
||||
uint8_t* sha1_result(sha1nfo *s);
|
||||
|
||||
void SHA1_Init(SHA_CTX*);
|
||||
#define SHA1_Update(pctx, pkeyResult, keyResultLen) sha1_write(pctx, pkeyResult, keyResultLen)
|
||||
#define SHA1_Final(shavalue, pctx) memcpy(shavalue, sha1_result(pctx), 20);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user