/**************************************************************************
*** COPYRIGHT (c) 2002 by TransNexus, Inc. ***
*** ***
*** This software is property of TransNexus, Inc. ***
*** This software is freely available under license from TransNexus. ***
*** The license terms and conditions for free use of this software by ***
*** third parties are defined in the OSP Toolkit Software License ***
*** Agreement (LICENSE.txt). Any use of this software by third ***
*** parties, which does not comply with the terms and conditions of the ***
*** OSP Toolkit Software License Agreement is prohibited without ***
*** the prior, express, written consent of TransNexus, Inc. ***
*** ***
*** Thank you for using the OSP ToolKit(TM). Please report any bugs, ***
*** suggestions or feedback to support@transnexus.com ***
*** ***
**************************************************************************/
/* ospsocket.cpp - Socket functions. */
#include "osp/osp.h"
#include "osp/ospconfig.h"
#include "osp/ospsocket.h"
#include "osp/osputils.h"
#include "osp/ospcomm.h"
#include "osp/osphttp.h"
#include "osp/ospssl.h"
#ifndef _WIN32
#include <poll.h>
#endif
int OSPPSockClose(
OSPTBOOL ospvGracefulSSLShutdown,
OSPTSOCKET *ospvSockFd,
OSPTSSLSESSION ** SSLSession)
{
int tmperror = OSPC_ERR_NO_ERROR;
OSPM_DBGENTER(("ENTER: OSPPSockClose()\n"));
/* delete the SSL context if it's still hanging around */
OSPPSSLSessionDelete(ospvGracefulSSLShutdown, SSLSession);
if (*ospvSockFd != OSPC_SOCK_INVALID) {
OSPM_CLOSE(*ospvSockFd, tmperror);
*ospvSockFd = OSPC_SOCK_INVALID;
}
OSPM_DBGEXIT(("EXIT : OSPPSockClose()\n"));
return OSPC_ERR_NO_ERROR;
}
const char *OSPM_INET_NTOA(
OSPTIPADDR ip,
char *buffer,
socklen_t length)
{
struct in_addr sin;
sin.s_addr = (ip);
return (inet_ntop(AF_INET, &sin, buffer, length));
}
int OSPPSockConnect(
OSPTSOCKET *ospvSockFd,
OSPTBOOL ospvBlocking,
OSPTIPADDR ospvIpAddr,
unsigned short ospvPort,
struct timeval *ospvTimeout,
OSPTSSLSESSION **ospvSSLSession)
{
int errorcode = OSPC_ERR_NO_ERROR;
char ErrStr[200];
char buffer[INET_ADDRSTRLEN];
/*
* set the connection socket.
* This will also affect reads and writes.
*/
errorcode = OSPPSockSetBlockingIO(*ospvSockFd, ospvBlocking);
/*
* attempt connection
*/
if (errorcode == OSPC_ERR_NO_ERROR) {
OSPM_CONNECT(*ospvSockFd, ospvIpAddr, ospvPort, errorcode);
if ((errorcode != OSPC_ERR_NO_ERROR) && (errorcode != OSPC_ERR_SOCK_CONN_IN_PROGRESS)) {
errorcode = OSPC_ERR_SOCK_CONNECT_FAILED;
#ifdef _WIN32
OSPM_DBGERROR(("Could not connect to %s:%d .Check IP Address and Port Numbers again. Error = %d\n",
OSPM_INET_NTOA(ospvIpAddr, buffer, INET_ADDRSTRLEN), ntohs(ospvPort), errorcode));
sprintf(ErrStr, "Cannot communicate with application. Connection timed out to IP address: %s",
OSPM_INET_NTOA(ospvIpAddr, buffer, INET_ADDRSTRLEN));
OSPM_DBGERRORLOG(errorcode, ErrStr);
#else
OSPM_DBGERROR(("%s to %s:%d .Check IP Address and Port Numbers again. Error = %d\n", strerror(errno),
OSPM_INET_NTOA(ospvIpAddr, buffer, INET_ADDRSTRLEN), ntohs(ospvPort), errorcode));
sprintf(ErrStr, "Cannot communicate with application. Connection timed out to IP address: %s",
OSPM_INET_NTOA(ospvIpAddr, buffer, INET_ADDRSTRLEN));
OSPM_DBGERRORLOG(errorcode, ErrStr);
#endif
OSPPSockClose(OSPC_FALSE, ospvSockFd, ospvSSLSession);
} else {
/*
* use the configured timeout to limit how
* long to wait for a connection
*/
errorcode = OSPPSockWaitTillReady(*ospvSockFd, OSPC_FALSE, ospvTimeout);
if (errorcode != OSPC_ERR_NO_ERROR) {
errorcode = OSPC_ERR_SOCK_CONNECT_FAILED;
#ifdef _WIN32
OSPM_DBGERROR(("Could not connect to %s:%d .Check IP Address and Port Numbers again. Error = %d\n",
OSPM_INET_NTOA(ospvIpAddr, buffer, INET_ADDRSTRLEN), ntohs(ospvPort), errorcode));
sprintf(ErrStr, "Cannot communicate with application. Connection timed out to IP address: %s",
OSPM_INET_NTOA(ospvIpAddr, buffer, INET_ADDRSTRLEN));
OSPM_DBGERRORLOG(errorcode, ErrStr);
#else
OSPM_DBGERROR(("%s to %s:%d .Check IP Address and Port Numbers again. Error = %d\n", strerror(errno),
OSPM_INET_NTOA(ospvIpAddr, buffer, INET_ADDRSTRLEN), ntohs(ospvPort), errorcode));
sprintf(ErrStr, "Cannot communicate with application. Connection timed out to IP address: %s",
OSPM_INET_NTOA(ospvIpAddr, buffer, INET_ADDRSTRLEN));
OSPM_DBGERRORLOG(errorcode, ErrStr);
#endif
OSPPSockClose(OSPC_FALSE, ospvSockFd, ospvSSLSession);
}
}
}
return errorcode;
}
int OSPPSockConnectAuditURL(
OSPTHTTP *ospvHttp,
OSPTBOOL *ospvConnected)
{
int errorcode = OSPC_ERR_NO_ERROR;
OSPTCOMM *comm = OSPC_OSNULL;
struct timeval timeout;
unsigned socktimeout = 0;
OSPM_DBGENTER(("ENTER: OSPPSockConnectAuditURL()\n"));
if (ospvHttp == OSPC_OSNULL) {
errorcode = OSPC_ERR_HTTP_INVALID_ARG;
}
/*
* see if the socket is or has been connected. If so, shut it
* down now.
*/
if (errorcode == OSPC_ERR_NO_ERROR) {
if (ospvHttp->SockFd != OSPC_SOCK_INVALID) {
errorcode = OSPPSockClose(OSPC_FALSE, &(ospvHttp->SockFd), &(ospvHttp->SSLSession));
if (errorcode != OSPC_ERR_NO_ERROR) {
errorcode = OSPC_ERR_SOCK_CLOSE_FAILED;
OSPM_DBGERRORLOG(errorcode, "cannot close socket");
}
}
}
if (errorcode == OSPC_ERR_NO_ERROR) {
/*
* create a new socket
*/
errorcode = OSPPSockNew(ospvHttp);
if (errorcode != OSPC_ERR_NO_ERROR) {
errorcode = OSPC_ERR_SOCK_CREATE_FAILED;
OSPM_DBGERRORLOG(errorcode, "cannot create socket");
} else {
comm = (OSPTCOMM *)ospvHttp->Comm;
/* get auditURL svcpt */
ospvHttp->ServicePoint = comm->AuditURL;
/*
* perform actual connection attempt
*/
OSPM_DBGNET(("connecting to %s%s", ospvHttp->ServicePoint->HostName, ospvHttp->ServicePoint->URI));
if (ospvHttp->ServicePoint != OSPC_OSNULL) {
ospvHttp->Flags = (unsigned char)
(ospvHttp->Flags & OSPC_SOCK_CONNECTED_MASK);
/*
* set the response timeout for the socket
*/
OSPPCommGetTimeout((OSPTCOMM *)ospvHttp->Comm, &socktimeout);
timeout.tv_sec = socktimeout / 1000;
timeout.tv_usec = socktimeout % 1000 * 1000;
/*
** CHANGED OSPCFALSE -> OSPCTRUE in Sock conenct experimental
*/
errorcode = OSPPSockConnect(&(ospvHttp->SockFd), OSPC_DEFAULT_BLOCKING_FLAG,
ospvHttp->ServicePoint->IpAddr, ospvHttp->ServicePoint->Port, &timeout, &(ospvHttp->SSLSession));
if (errorcode == OSPC_ERR_NO_ERROR) {
if (errorcode == OSPC_ERR_NO_ERROR) {
/*
* begin an SSL Session if a secured connection
* is required
*/
errorcode = OSPPSSLSessionNew(ospvHttp, comm->Security);
if (errorcode == OSPC_ERR_NO_ERROR) {
*ospvConnected = OSPC_TRUE;
ospvHttp->Flags |= OSPC_SOCK_CONNECTED_BIT;
} else {
OSPPSockClose(OSPC_FALSE, &(ospvHttp->SockFd), &(ospvHttp->SSLSession));
}
}
}
} else {
errorcode = OSPC_ERR_COMM_NO_SVC_PTS_AVAIL;
OSPM_DBGERRORLOG(errorcode, "no svc pt avail");
}
}
}
OSPM_DBGEXIT(("EXIT : OSPPSockConnectAuditURL() (%d)\n", errorcode));
return errorcode;
}
int OSPPSockConnectServicePoint(
OSPTHTTP *ospvHttp,
OSPTBOOL *ospvRollover,
OSPTBOOL *ospvConnected)
{
unsigned numsvcpts = 0, socktimeout = 0;
OSPTSVCPT *svcptlist = OSPC_OSNULL, *svcptitem = OSPC_OSNULL;
int errorcode = OSPC_ERR_NO_ERROR;
struct timeval timeout;
OSPTCOMM *comm = OSPC_OSNULL;
OSPM_DBGENTER(("ENTER: OSPPSockConnectServicePoint()\n"));
if (ospvHttp == OSPC_OSNULL) {
errorcode = OSPC_ERR_HTTP_INVALID_ARG;
}
/*
* see if the socket is or has been connected. If so, shut it
* down now.
*/
if (errorcode == OSPC_ERR_NO_ERROR) {
if (ospvHttp->SockFd != OSPC_SOCK_INVALID) {
errorcode = OSPPSockClose(OSPC_FALSE, &(ospvHttp->SockFd), &(ospvHttp->SSLSession));
if (errorcode != OSPC_ERR_NO_ERROR) {
errorcode = OSPC_ERR_SOCK_CLOSE_FAILED;
OSPM_DBGERRORLOG(errorcode, "cannot close socket");
}
}
}
if (errorcode == OSPC_ERR_NO_ERROR) {
/*
* create a new socket
*/
errorcode = OSPPSockNew(ospvHttp);
if (errorcode != OSPC_ERR_NO_ERROR) {
errorcode = OSPC_ERR_SOCK_CREATE_FAILED;
OSPM_DBGERRORLOG(errorcode, "cannot create socket");
} else {
comm = (OSPTCOMM *)ospvHttp->Comm;
errorcode = OSPPCommGetNumberOfServicePoints(comm, &numsvcpts);
if (numsvcpts == 0) {
OSPM_DBGERRORLOG(OSPC_ERR_COMM_NO_SVC_PTS, "num of svc pts = 0");
errorcode = OSPC_ERR_COMM_NO_SVC_PTS;
} else {
if (errorcode == OSPC_ERR_NO_ERROR) {
/*
* get a pointer to the service point list
*/
osppHttpGetServicePointList(ospvHttp, &svcptlist);
/*
* if the http connection has never been connected or
* the service point list has been exhausted, get the
* first service point in the list
*/
if (ospvHttp->ServicePoint == OSPC_OSNULL) {
ospvHttp->ServicePoint = (OSPTSVCPT *)OSPPListFirst((OSPTLIST *)& svcptlist);
} else {
ospvHttp->ServicePoint = (OSPTSVCPT *)OSPPListNext((OSPTLIST *)& svcptlist, ospvHttp->ServicePoint);
/*
* let the calling function know that the
* service point list has been rolled over
* to the beginning
*/
if (ospvHttp->ServicePoint == OSPC_OSNULL) {
ospvHttp->ServicePoint = (OSPTSVCPT *)OSPPListFirst((OSPTLIST *)& svcptlist);
}
}
/*
* if the next item in the service point list is null,
* then the list is exhausted
*/
if ((svcptitem = (OSPTSVCPT *)OSPPListNext((OSPTLIST *)& svcptlist, ospvHttp->ServicePoint)) == OSPC_OSNULL) {
*ospvRollover = OSPC_TRUE;
}
/*
* perform actual connection attempt
*/
OSPM_DBGNET(("connecting to %s%s", ospvHttp->ServicePoint->HostName, ospvHttp->ServicePoint->URI));
if (ospvHttp->ServicePoint != OSPC_OSNULL) {
ospvHttp->Flags = (unsigned char)(ospvHttp->Flags & OSPC_SOCK_CONNECTED_MASK);
/*
* set the response timeout for the socket
*/
OSPPCommGetTimeout((OSPTCOMM *)ospvHttp->Comm, &socktimeout);
timeout.tv_sec = socktimeout / 1000;
timeout.tv_usec = socktimeout % 1000 * 1000;
/*
* CHANGED OSPCFALSE -> TRUE
*/
errorcode = OSPPSockConnect(&(ospvHttp->SockFd), OSPC_DEFAULT_BLOCKING_FLAG,
ospvHttp->ServicePoint->IpAddr, ospvHttp->ServicePoint->Port, &timeout, &(ospvHttp->SSLSession));
if (errorcode == OSPC_ERR_NO_ERROR) {
/*
* begin an SSL Session if a secured connection
* is required
*/
errorcode = OSPPSSLSessionNew(ospvHttp, comm->Security);
if (errorcode == OSPC_ERR_NO_ERROR) {
*ospvConnected = OSPC_TRUE;
ospvHttp->Flags |= OSPC_SOCK_CONNECTED_BIT;
} else {
OSPPSockClose(OSPC_FALSE, &(ospvHttp->SockFd), &(ospvHttp->SSLSession));
}
}
} else {
errorcode = OSPC_ERR_COMM_NO_SVC_PTS_AVAIL;
OSPM_DBGERRORLOG(errorcode, "no svc pts avail");
}
}
}
}
}
OSPM_DBGEXIT(("EXIT : OSPPSockConnectServicePoint() (%d)\n", errorcode));
return errorcode;
}
int OSPPSockDisableNagle(
OSPTHTTP *ospvHttp)
{
int errorcode = OSPC_ERR_NO_ERROR;
OSPM_DBGENTER(("ENTER: OSPPSockDisableNagle()\n"));
OSPM_DISABLE_NAGLE(ospvHttp->SockFd, errorcode);
if (errorcode != OSPC_ERR_NO_ERROR) {
errorcode = OSPC_ERR_SOCK_DISABLE_NAGLE_FAILED;
}
OSPM_DBGEXIT(("EXIT : OSPPSockDisableNagle()\n"));
return errorcode;
}
int OSPPSockGetHostIP(
char *Host,
OSPTIPADDR *ospvIpAddr)
{
int errorcode = OSPC_ERR_NO_ERROR;
OSPM_DBGENTER(("ENTER: OSPPSockGetHostIP()\n"));
/*
* see if char IP was passed
*/
OSPM_INET_ADDR((const char *)Host, *ospvIpAddr);
if (*ospvIpAddr)
return errorcode;
OSPM_GETHOSTBYNAME(Host, *ospvIpAddr, errorcode);
OSPM_DBGEXIT(("EXIT : OSPPSockGetHostIP() (%d)\n", errorcode));
return errorcode;
}
int OSPPSockNew(
OSPTHTTP *ospvHttp)
{
int errorcode = OSPC_ERR_NO_ERROR;
OSPM_DBGENTER(("ENTER: OSPPSockNew()\n"));
/* create the socket */
OSPM_SOCKET(ospvHttp->SockFd, errorcode);
if (errorcode == OSPC_ERR_NO_ERROR) {
errorcode = OSPPSockSetKeepAlive(ospvHttp);
if (errorcode == OSPC_ERR_NO_ERROR) {
errorcode = OSPPSockDisableNagle(ospvHttp);
}
}
OSPM_DBGEXIT(("EXIT : OSPPSockNew() (%d)\n", errorcode));
return errorcode;
}
void OSPPSockProcessRequest(
OSPTHTTP *ospvHttp,
unsigned char *ospvRequestBuffer,
unsigned ospvRequestBufferSz,
unsigned char **ospvResponseBuffer,
unsigned *ospvResponseBufferSz,
unsigned char **ospvContentBuffer,
unsigned *ospvContentBufferSz,
int *ospvError)
{
#define OSPC_RECVBUF_SZ 256
char recvheadbuf[OSPC_RECVBUF_SZ] = { "" };
unsigned recvheadbufsz = OSPC_RECVBUF_SZ;
int responsetype = 0;
int connectionCloseFlag = OSPC_FALSE;
unsigned char *tmpConnectionBuffer = OSPC_OSNULL;
unsigned tmpConnectionBufferSz = 0;
unsigned char *tmpReceiveBuffer = OSPC_OSNULL;
unsigned tmpReceiveBufferSz = 0;
unsigned char *tmpContentBuffer = OSPC_OSNULL;
unsigned tmpContentBufferSz = 0;
char buffer[INET_ADDRSTRLEN];
OSPM_DBGENTER(("ENTER: OSPPSockProcessRequest()\n"));
/*
* set the default value.
*/
*ospvResponseBuffer = OSPC_OSNULL;
*ospvResponseBufferSz = 0;
*ospvError = OSPC_ERR_NO_ERROR;
if (ospvHttp == OSPC_OSNULL) {
*ospvError = OSPC_ERR_HTTP_INVALID_ARG;
}
/*
* send the outbound message to the service point.
* this consists of the HTTP header and the multipart MIME message
*/
if (*ospvError == OSPC_ERR_NO_ERROR) {
*ospvError = OSPPSSLSessionWrite(ospvHttp, ospvRequestBuffer, &ospvRequestBufferSz);
if (*ospvError == OSPC_ERR_NO_ERROR) {
/* make sure socket was not reset by peer */
OSPM_GETSOCKERR(ospvHttp, *ospvError);
}
}
if (*ospvError == OSPC_ERR_NO_ERROR) {
/*
* the first response that the server may send back to us
* could look like this:
*
* HTTP/1.1 100 Continue
* Server: Microsoft-IIS/4.0
* Date: Tue, 21 Jul 1998 00:39:54 GMT
*
* this simply confirms that the server has received our request.
* verify the '100 Continue' and continue.
*/
*ospvError = OSPPSSLSessionRead(ospvHttp, (unsigned char *)recvheadbuf, &recvheadbufsz, "\r\n\r\n");
/*
** Check this header to see what type of response we are getting.
** The type will be returned in the responsetype variable. If the
** type is something other than a 1xx or a 2xx, an errorcode will
** be returned by the function.
*/
if ((*ospvError != OSPC_ERR_NO_ERROR)) {
if ((*ospvError != OSPC_ERR_SOCK_SELECT_FAILED) && (*ospvError != OSPC_ERR_SOCK_RECV_FAILED) && (*ospvError != OSPC_ERR_SSL_READ_FAILED)) {
OSPM_DBGERRORLOG(*ospvError, "http recv init header failed");
}
} else if ((*ospvError = OSPPHttpVerifyResponse(recvheadbuf, &responsetype, ospvHttp)) != OSPC_ERR_NO_ERROR) {
if (*ospvError == OSPC_ERR_HTTP_BAD_REQUEST)
OSPM_DBGERRORLOG(*ospvError, "http response unexpected: Server unavailable at the URL specified.Modify URL and try again.");
} else {
if (responsetype == 100) {
/*
* Read again for the 200 header.
*/
recvheadbufsz = 256;
*ospvError = OSPPSSLSessionRead(ospvHttp, (unsigned char *)recvheadbuf, &recvheadbufsz, "\r\n\r\n");
responsetype = 0;
}
/*
* the header for the server response will look like this:
*
* HTTP/1.1 200 OK
* Server: Microsoft-IIS/4.0
* Date: Tue, 21 Jul 1998 00:39:56 GMT
* Connection: Keep-Alive
* Content-Length: 1042
* Content-type: .....
*/
/*
* parse the header response and place the content-length
* in the ospvInBufferSz variable. This is used to determine
* the size of the inbound response message buffer.
*/
if (*ospvError == OSPC_ERR_NO_ERROR) {
/*
* make sure we get an OK response back from the server
*/
if (((*ospvError = OSPPHttpVerifyResponse(recvheadbuf, &responsetype, ospvHttp)) != OSPC_ERR_NO_ERROR) || (responsetype != 200)) {
OSPM_DBGERRORLOG(*ospvError, "http bad server response error");
OSPM_DBGERROR(("expected 2xx code: received = [%s]\n", recvheadbuf));
} else {
/* parse the header response and place the MIME
* connection-type into the tmpConnectionBuffer variable.
* tmpConnectionBufferSz is set to the size of the
* tmpConnectionBuffer.
*/
OSPPHttpParseHeader((unsigned char *)recvheadbuf,
&tmpConnectionBuffer, &tmpConnectionBufferSz, OSPC_HTTP_CONNECTION_TYPE, ospvError);
/* check to see if the connection type contains "close".
* If so, then set a flag to eventually close the socket connection.
*/
if ((tmpConnectionBuffer != OSPC_OSNULL) && (tmpConnectionBufferSz > 0)) {
if (OSPM_STRSTR((char *)tmpConnectionBuffer, (const char *)"close") != OSPC_OSNULL) {
connectionCloseFlag = OSPC_TRUE;
}
}
if (tmpConnectionBuffer != OSPC_OSNULL) {
OSPM_FREE(tmpConnectionBuffer);
}
OSPM_DBGNET(("http header = [%s]", recvheadbuf));
/*
* parse the header response and place the MIME
* content-type into the tmpContentBuffer variable.
* tmpContentBufferSz is set to the size of the
* tmpContentBuffer.
*/
OSPPHttpParseHeader((unsigned char *)recvheadbuf, &tmpContentBuffer, &tmpContentBufferSz, OSPC_HTTP_CONTENT_TYPE, ospvError);
if (*ospvError == OSPC_ERR_NO_ERROR) {
/*
* parse the header response and place the
* content-length in the tmpReceiveBufferSz
* variable. This is used to determine
* the size of the inbound response message
* buffer. Alloc space for the tmpReceiveBuffer in order
* receive the content data.
*/
OSPPHttpParseHeader((unsigned char *)recvheadbuf,
&tmpReceiveBuffer, &tmpReceiveBufferSz, OSPC_HTTP_CONTENT_LENGTH, ospvError);
if (*ospvError == OSPC_ERR_NO_ERROR) {
/*
* now receive the body of the HTTP response
*/
*ospvError = OSPPSSLSessionRead(ospvHttp, tmpReceiveBuffer, &tmpReceiveBufferSz, OSPC_OSNULL);
if (*ospvError == OSPC_ERR_NO_ERROR) {
/*
* assign the response buffer pointer after all of the
* reading is complete. This needs to be an autonomous
* operation because the application thread is waiting for
* the buffer to become non-null in order to indicate that
* data is available to process. If the conditional variable
* receives a spurous wakeup (which happens on many SMP platforms)
* the buffer pointer must point to a complete response otherwise
* a partial message will attempt to be processed which will reek
* havoc on the request and possibly the application as well.
*/
*ospvResponseBuffer = tmpReceiveBuffer;
*ospvResponseBufferSz = tmpReceiveBufferSz;
OSPM_DBGNET(("http body = [%s]", tmpReceiveBuffer));
if (*ospvContentBuffer != OSPC_OSNULL) {
OSPM_FREE(*ospvContentBuffer);
*ospvContentBufferSz = 0;
}
/* Save the content buffer and content buffer size
* for the next time through this function
*/
*ospvContentBuffer = tmpContentBuffer;
*ospvContentBufferSz = tmpContentBufferSz;
} else {
if (tmpReceiveBuffer != OSPC_OSNULL) {
OSPM_FREE(tmpReceiveBuffer);
}
if (tmpContentBuffer != OSPC_OSNULL) {
OSPM_FREE(tmpContentBuffer);
}
}
} else {
if (tmpContentBuffer != OSPC_OSNULL) {
OSPM_FREE(tmpContentBuffer);
}
}
}
}
}
}
} else {
OSPM_DBGERROR(("Connection to application has been reset. IP address: %s",
OSPM_INET_NTOA(ospvHttp->ServicePoint->IpAddr, buffer, INET_ADDRSTRLEN)));
}
/* If the Connection-Type indicated "close" in the MIME header,
* then close the connection.
*/
if (connectionCloseFlag == OSPC_TRUE) {
*ospvError = OSPPSockClose(OSPC_TRUE, &(ospvHttp->SockFd), &(ospvHttp->SSLSession));
}
OSPM_DBGEXIT(("EXIT : OSPPSockProcessRequest() (%d)\n", *ospvError));
}
int OSPPSockRead(
OSPTHTTP *ospvHttp,
unsigned char *ospvBuffer,
unsigned int *ospvBufferSz)
{
int errorcode = OSPC_ERR_NO_ERROR;
unsigned length = 0;
struct timeval timeout;
unsigned socktimeout = 0;
char ErrStr[200];
char buffer[INET_ADDRSTRLEN];
OSPM_DBGENTER(("ENTER: OSPPSockRead()\n"));
OSPM_DBGNET(("NET : OSPPSockRead() bufsz = <%d>\n", *ospvBufferSz));
do {
/*
* set the response timeout for the socket
*/
OSPPCommGetTimeout((OSPTCOMM *)ospvHttp->Comm, &socktimeout);
timeout.tv_sec = socktimeout / 1000;
timeout.tv_usec = socktimeout % 1000 * 1000;
errorcode = OSPPSockWaitTillReady(ospvHttp->SockFd, OSPC_TRUE, &timeout);
if (errorcode == OSPC_ERR_NO_ERROR) {
OSPM_RECV(ospvHttp, ospvBuffer + length, *ospvBufferSz - length, errorcode);
length += ospvHttp->ByteCount;
} else {
OSPM_DBGERROR(("Response timed out. Server unavailable on %s:%d Error = %d\n",
OSPM_INET_NTOA(ospvHttp->ServicePoint->IpAddr, buffer, INET_ADDRSTRLEN), ntohs(ospvHttp->ServicePoint->Port), errorcode));
sprintf(ErrStr, "Application slow in responding, response timed out to IP address: %s",
OSPM_INET_NTOA(ospvHttp->ServicePoint->IpAddr, buffer, INET_ADDRSTRLEN));
OSPM_DBGERRORLOG(errorcode, ErrStr);
}
} while (errorcode == OSPC_ERR_NO_ERROR && ospvHttp->ByteCount > 0 && length < *ospvBufferSz);
if (errorcode != OSPC_ERR_SOCK_SELECT_FAILED)
if (length != *ospvBufferSz || errorcode != OSPC_ERR_NO_ERROR) {
OSPM_DBGNET(("NET : OSPPSockRead() failed len = <%d> bufsz = <%d> err = <%d>\n", length, *ospvBufferSz, errorcode));
errorcode = OSPC_ERR_SOCK_RECV_FAILED;
OSPM_DBGERROR(("Connection reset by peer on %s:%d Error = %d\n", OSPM_INET_NTOA(ospvHttp->ServicePoint->IpAddr, buffer, INET_ADDRSTRLEN),
ntohs(ospvHttp->ServicePoint->Port), errorcode));
sprintf(ErrStr, "Connection to application has been reset. IP address: %s",
OSPM_INET_NTOA(ospvHttp->ServicePoint->IpAddr, buffer, INET_ADDRSTRLEN));
OSPM_DBGERRORLOG(errorcode, ErrStr);
}
*ospvBufferSz = length;
OSPM_DBGEXIT(("EXIT : OSPPSockRead() (%d)\n", errorcode));
return errorcode;
}
int OSPPSockSetBlockingIO(
OSPTSOCKET ospvSockFd,
OSPTBOOL ospvBlocking)
{
int errorcode = OSPC_ERR_NO_ERROR;
OSPM_DBGENTER(("ENTER: OSPPSockSetBlockingIO()\n"));
OSPM_BLOCKIO(ospvSockFd, ospvBlocking, errorcode);
if (errorcode != OSPC_ERR_NO_ERROR)
errorcode = OSPC_ERR_SOCK_BLOCKIO_FAILED;
OSPM_DBGEXIT(("EXIT : OSPPSockSetBlockingIO()\n"));
return errorcode;
}
int OSPPSockSetKeepAlive(
OSPTHTTP *ospvHttp)
{
int optval = 1;
int errorcode = OSPC_ERR_NO_ERROR;
OSPM_DBGENTER(("ENTER: OSPPSockSetKeepAlive()\n"));
OSPM_SETSOCKOPT(ospvHttp->SockFd, SOL_SOCKET, SO_KEEPALIVE, optval, sizeof(optval), errorcode);
OSPM_DBGEXIT(("EXIT : OSPPSockSetKeepAlive()\n"));
return errorcode;
}
int OSPPSockWaitTillReady(
OSPTSOCKET ospvSockFd,
OSPTBOOL ospvWaitForRead,
struct timeval *ospvTimeout)
{
int errorcode = OSPC_ERR_NO_ERROR;
OSPM_DBGENTER(("ENTER: OSPPSockWaitTillReady()\n"));
#ifdef _WIN32
fd_set fdlist;
unsigned fdready = 0;
if (errorcode == OSPC_ERR_NO_ERROR) {
FD_ZERO(&fdlist);
FD_SET(ospvSockFd, &fdlist);
/*
* make sure there is data available to read
*/
if (ospvWaitForRead) {
OSPM_SELECT(ospvSockFd + 1, &fdlist, OSPC_OSNULL, OSPC_OSNULL, ospvTimeout, fdready);
} else {
/*
* make sure there is data available to write
*/
OSPM_SELECT(ospvSockFd + 1, OSPC_OSNULL, &fdlist, OSPC_OSNULL, ospvTimeout, fdready);
}
if (fdready != 1)
errorcode = OSPC_ERR_SOCK_SELECT_FAILED;
}
#else
short events;
struct pollfd fd;
int timeout = ospvTimeout->tv_sec * 1000 + ospvTimeout->tv_usec;
int fdready;
if (ospvWaitForRead) {
/* make sure there is data available to read */
events = POLLIN;
} else {
/* make sure there is data available to write */
events = POLLOUT;
}
fd.fd = ospvSockFd;
fd.events = events;
fd.revents = 0;
fdready = poll(&fd, 1, timeout);
if ((fdready != 1) || !(fd.revents & events)) {
errorcode = OSPC_ERR_SOCK_SELECT_FAILED;
}
#endif
OSPM_DBGEXIT(("EXIT : OSPPSockWaitTillReady() select on %s to.sec(%ld) to.usec(%ld) fdready(%d) err(%d)\n",
(ospvWaitForRead ? "read" : "write"), ospvTimeout->tv_sec, ospvTimeout->tv_usec, fdready, errorcode));
return errorcode;
}
int OSPPSockWrite(
OSPTHTTP *ospvHttp,
unsigned char *ospvBuffer,
unsigned int *ospvBufferSz)
{
int errorcode = OSPC_ERR_NO_ERROR;
unsigned length = 0;
struct timeval timeout;
OSPM_DBGENTER(("ENTER: OSPPSockWrite()\n"));
do {
timeout.tv_sec = 0l;
timeout.tv_usec = 0l;
errorcode = OSPPSockWaitTillReady(ospvHttp->SockFd, OSPC_FALSE, &timeout);
if (errorcode == OSPC_ERR_NO_ERROR) {
OSPM_SEND(ospvHttp->SockFd, ospvHttp->ByteCount, ospvBuffer + length, *ospvBufferSz - length, errorcode);
length += ospvHttp->ByteCount;
}
} while (errorcode == OSPC_ERR_NO_ERROR && ospvHttp->ByteCount > 0 && length < *ospvBufferSz);
if (length != *ospvBufferSz || errorcode != OSPC_ERR_NO_ERROR)
errorcode = OSPC_ERR_SOCK_SEND_FAILED;
*ospvBufferSz = length;
OSPM_DBGEXIT(("EXIT : OSPPSockWrite() (%d)\n", errorcode));
return errorcode;
}