/*
* This code implements communication based on Miranda netlib library
*
* (c) majvan 2002-2004
*/
#include "../stdafx.h"
//--------------------------------------------------------------------------------------------------
BOOL SSLLoaded = FALSE;
HNETLIBUSER hNetlibUser = nullptr;
HANDLE RegisterNLClient(char *name)
{
#ifdef DEBUG_COMM
mir_writeLogA(CommFile, "");
#endif
NETLIBUSER nlu = {};
nlu.flags = NUF_OUTGOING | NUF_HTTPCONNS;
nlu.szDescriptiveName.a = name;
nlu.szSettingsModule = (char *)name;
hNetlibUser = Netlib_RegisterUser(&nlu);
#ifdef DEBUG_COMM
if (NULL == hNetlibUser)
mir_writeLogA(CommFile, "\n");
else
mir_writeLogA(CommFile, "\n");
#endif
return hNetlibUser;
}
//Move connection to SSL
void CNLClient::SSLify()
{
#ifdef DEBUG_COMM
Netlib_Log(hNetlibUser, "Staring SSL...");
#endif
int socket = Netlib_GetSocket(hConnection);
if (socket != INVALID_SOCKET) {
#ifdef DEBUG_COMM
Netlib_Log(hNetlibUser, "Staring netlib core SSL");
#endif
if (Netlib_StartSsl(hConnection, nullptr)) {
#ifdef DEBUG_COMM
Netlib_Log(hNetlibUser, "Netlib core SSL started");
#endif
isTLSed = true;
SSLLoaded = TRUE;
return;
}
}
//ssl could not be created
throw NetworkError = (uint32_t)ESSL_CREATESSL;
}
//Connects to the server through the sock
//if not success, exception is throwed
void CNLClient::Connect(const char *servername, const int port)
{
NetworkError = SystemError = 0;
isTLSed = false;
#ifdef DEBUG_COMM
mir_writeLogA(CommFile, "\n");
#endif
try {
if (nullptr == (hConnection = Netlib_OpenConnection(hNetlibUser, servername, port))) {
SystemError = WSAGetLastError();
throw NetworkError = (uint32_t)ENL_CONNECT;
}
#ifdef DEBUG_COMM
mir_writeLogA(CommFile, "\n");
#endif
return;
}
catch (...) {
#ifdef DEBUG_COMM
mir_writeLogA(CommFile, "\n");
#endif
throw;
}
}
//Performs a simple query
// query- command to send
int CNLClient::LocalNetlib_Send(HNETLIBCONN hConn, const char *buf, int len, int flags)
{
return Netlib_Send(hConn, buf, len, flags);
}
void CNLClient::Send(const char *query)
{
unsigned int Sent;
if (nullptr == query)
return;
if (hConnection == nullptr)
return;
#ifdef DEBUG_COMM
mir_writeLogA(CommFile, "%s", query);
#endif
try {
if ((SOCKET_ERROR == (Sent = LocalNetlib_Send(hConnection, query, (int)mir_strlen(query), MSG_DUMPASTEXT))) || Sent != (unsigned int)mir_strlen(query)) {
SystemError = WSAGetLastError();
throw NetworkError = (uint32_t)ENL_SEND;
}
#ifdef DEBUG_COMM
mir_writeLogA(CommFile, "\n");
#endif
}
catch (...) {
#ifdef DEBUG_COMM
mir_writeLogA(CommFile, "\n");
#endif
throw;
}
}
//Reads data from socket
// buf- buffer where to store max. buflen of received characters
// if buf is NULL, creates buffer of buflen size
// buf is NULL by default
//You need free() returned buffer, which can be allocated in this function
//if not success, exception is throwed
int CNLClient::LocalNetlib_Recv(HNETLIBCONN hConn, char *buf, int len, int flags)
{
int iReturn = Netlib_Recv(hConn, buf, len, flags);
if (isTLSed) {
#ifdef DEBUG_COMM
Netlib_Logf(hNetlibUser, "SSL recv: %s", buf);
#endif
}
return iReturn;
}
char *CNLClient::Recv(char *buf, int buflen)
{
#ifdef DEBUG_COMM
mir_writeLogA(CommFile, "");
#endif
try {
if (buf == nullptr)
buf = (char *)malloc(sizeof(char) * (buflen + 1));
if (buf == nullptr)
throw NetworkError = (uint32_t)ENL_RECVALLOC;
if (!isTLSed) {
NETLIBSELECT nls = {};
nls.dwTimeout = 60000;
nls.hReadConns[0] = hConnection;
switch (Netlib_Select(&nls)) {
case SOCKET_ERROR:
free(buf);
SystemError = WSAGetLastError();
throw NetworkError = (uint32_t)ENL_RECV;
case 0: // time out!
free(buf);
throw NetworkError = (uint32_t)ENL_TIMEOUT;
}
}
memset(buf, 0, buflen);
if (SOCKET_ERROR == (Rcv = LocalNetlib_Recv(hConnection, buf, buflen, MSG_DUMPASTEXT))) {
free(buf);
SystemError = WSAGetLastError();
throw NetworkError = (uint32_t)ENL_RECV;
}
if (!Rcv) {
free(buf);
SystemError = WSAGetLastError();
throw NetworkError = (uint32_t)ENL_RECV;
}
#ifdef DEBUG_COMM
*(buf + Rcv) = 0; //end the buffer to write it to file
mir_writeLogA(CommFile, "%s", buf);
mir_writeLogA(CommFile, "\n");
#endif
return(buf);
}
catch (...) {
#ifdef DEBUG_COMM
mir_writeLogA(CommFile, "\n");
#endif
throw;
}
}
//Closes netlib connection
void CNLClient::Disconnect()
{
Netlib_CloseHandle(hConnection);
hConnection = nullptr;
}
//Uninitializes netlib library
void UnregisterNLClient()
{
#ifdef DEBUG_COMM
mir_writeLogA(CommFile, "");
#endif
Netlib_CloseHandle(hNetlibUser);
hNetlibUser = nullptr;
#ifdef DEBUG_COMM
mir_writeLogA(CommFile, "\n");
#endif
}