#include "pmint.h"
#include "pmdb.h"
#include "config.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#if defined(X_NOT_POSIX) && defined(SIGNALRETURNSINT)
#define SIGVAL int
#else
#define SIGVAL void
#endif
typedef SIGVAL (*Signal_Handler)(int);
static proxy_service *proxyServiceList = NULL;
static Signal_Handler
Signal (int sig, Signal_Handler handler)
{
#ifndef X_NOT_POSIX
struct sigaction sigact, osigact;
sigact.sa_handler = handler;
sigemptyset(&sigact.sa_mask);
sigact.sa_flags = 0;
sigaction(sig, &sigact, &osigact);
return osigact.sa_handler;
#else
return signal(sig, handler);
#endif
}
proxy_service *
FindProxyService (
char *serviceName,
Bool createIf)
{
proxy_service *service = proxyServiceList;
int nameLen = strlen (serviceName);
while (service)
{
if (strcmp (service->serviceName, serviceName) == 0)
return service;
else if (ncasecmp (service->serviceName, serviceName, nameLen) == 0)
return service;
else
service = service->next;
}
if (createIf) {
service = (proxy_service *) malloc (sizeof (proxy_service));
if (!service)
return NULL;
service->serviceName = (char *) malloc (nameLen + 1);
if (!service->serviceName)
{
free (service);
return NULL;
}
strcpy (service->serviceName, serviceName);
service->proxyCount = 0;
service->proxyList = NULL;
if (proxyServiceList == NULL)
{
proxyServiceList = service;
service->next = NULL;
}
else
{
service->next = proxyServiceList;
proxyServiceList = service;
}
}
return service;
}
running_proxy *
StartNewProxy (
char *serviceName,
char *startCommand)
{
proxy_service *service = FindProxyService (serviceName, True);
running_proxy *proxy;
if (!service)
return NULL;
proxy = (running_proxy *) malloc (sizeof (running_proxy));
if (!proxy)
return NULL;
proxy->active = 0;
proxy->pmConn = NULL;
proxy->requests = NULL;
proxy->servers = NULL;
proxy->refused_service = False;
if (service->proxyList == NULL)
{
service->proxyList = proxy;
proxy->next = NULL;
}
else
{
proxy->next = service->proxyList;
service->proxyList = proxy;
}
if (system (startCommand) == -1)
{
printf ("unable to start managed proxy: %s\n", startCommand);
service->proxyList = proxy->next;
free (proxy);
return NULL;
}
if (verbose) {
printf ("started managed proxy: %s\n", startCommand);
printf ("waiting for StartProxy message\n");
}
service->proxyCount++;
return proxy;
}
running_proxy *
ConnectToProxy (
int pmOpcode,
char *serviceName,
char *proxyAddress)
{
proxy_service *service = FindProxyService (serviceName, True);
running_proxy *proxy;
IceConn proxy_iceConn;
PMconn *pmConn;
if (!service)
return NULL;
{
int majorVersion, minorVersion;
char *vendor, *release;
char errorString[256];
Signal (SIGPIPE, SIG_IGN);
proxy_iceConn = IceOpenConnection( proxyAddress, NULL,
False, pmOpcode,
sizeof(errorString), errorString);
Signal (SIGPIPE, SIG_DFL);
if (! proxy_iceConn) {
printf("unable to open connection to unmanaged proxy \"%s\" at %s\n",
serviceName, proxyAddress);
return NULL;
}
SetCloseOnExec (IceConnectionNumber (proxy_iceConn));
pmConn = (PMconn *) malloc (sizeof (PMconn));
if (pmConn == NULL) {
IceCloseConnection (proxy_iceConn);
return NULL;
}
if (IceProtocolSetup (proxy_iceConn, pmOpcode,
(IcePointer)pmConn,
False,
&majorVersion, &minorVersion,
&vendor, &release,
sizeof(errorString), errorString)
!= IceProtocolSetupSuccess) {
IceCloseConnection (proxy_iceConn);
free (pmConn);
printf ("Could not initialize proxy management protocol with\n unmanaged proxy \"%s\" at address %s:\n %s\n",
serviceName, proxyAddress, errorString);
return NULL;
}
pmConn->iceConn = proxy_iceConn;
pmConn->pmOpcode = pmOpcode;
pmConn->proto_major_version = majorVersion;
pmConn->proto_minor_version = minorVersion;
pmConn->vendor = vendor;
pmConn->release = release;
}
proxy = (running_proxy *) malloc (sizeof (running_proxy));
if (!proxy) {
IceCloseConnection (proxy_iceConn);
free (pmConn);
return NULL;
}
proxy->active = 1;
proxy->pmConn = pmConn;
proxy->requests = NULL;
proxy->servers = NULL;
proxy->refused_service = False;
if (service->proxyList == NULL)
{
service->proxyList = proxy;
proxy->next = NULL;
}
else
{
proxy->next = service->proxyList;
service->proxyList = proxy;
}
if (verbose)
printf ("connected to unmanaged proxy: %s at %s\n",
serviceName, proxyAddress);
service->proxyCount++;
return proxy;
}
Status
ActivateProxyService (
char *serviceName,
PMconn *pmConn)
{
proxy_service *service = FindProxyService (serviceName, False);
running_proxy *proxy;
if (!service)
return 0;
proxy = service->proxyList;
while (proxy)
{
if (!proxy->active)
{
proxy->active = 1;
proxy->pmConn = pmConn;
return 1;
}
else
proxy = proxy->next;
}
return 0;
}
void
ProxyGone (
IceConn proxyIceConn,
Bool *activeReqs)
{
proxy_service *service = proxyServiceList;
while (service)
{
running_proxy *proxy = service->proxyList;
running_proxy *prevProxy = NULL;
while (proxy)
{
if (proxy->pmConn && (proxy->pmConn->iceConn == proxyIceConn))
{
server_list *server;
request_list *req;
if (verbose)
printf ("Proxy disconnected on fd %d",
IceConnectionNumber(proxyIceConn));
server = proxy->servers;
if (verbose && server)
fputs (" for server", stdout);
while (server)
{
server_list *next_server = server->next;
if (verbose) {
fputc (' ', stdout);
fputs (server->serverAddress, stdout);
}
free (server->serverAddress);
free (server);
server = next_server;
}
if (verbose)
fputc ('\n', stdout);
if (prevProxy == NULL)
service->proxyList = proxy->next;
else
prevProxy->next = proxy->next;
service->proxyCount--;
*activeReqs = proxy->requests != NULL;
req = proxy->requests;
while (req)
{
request_list *nextreq = req->next;
if (req->requestor) {
assert (req->requestor->iceConn != NULL);
if (verbose)
printf ("Reprocessing request from fd %d for service %s at %s\n",
IceConnectionNumber (req->requestor->iceConn),
req->serviceName, req->serverAddress);
ForwardRequest( req->requestor,
req->serviceName, req->serverAddress,
req->hostAddress, req->startOptions,
req->authLen, req->authName,
req->authData);
}
if (req->serviceName)
free (req->serviceName);
if (req->serverAddress)
free (req->serverAddress);
if (req->hostAddress)
free (req->hostAddress);
if (req->startOptions)
free (req->startOptions);
if (req->listData)
free (req->listData);
if (req->authName)
free (req->authName);
if (req->authData)
free (req->authData);
free (req);
req = nextreq;
}
free (proxy);
return;
}
else if (proxy->requests) {
request_list **prev_reqP = &proxy->requests;
request_list *req = proxy->requests;
while (req) {
if (req->requestor->iceConn == proxyIceConn) {
if (verbose) {
printf ("Requestor disconnected on fd %d while awaiting reply\n for service %s (%s)",
IceConnectionNumber(proxyIceConn),
req->serviceName, req->serverAddress);
if (proxy->pmConn && proxy->pmConn->iceConn) {
printf (" from proxy on fd %d\n",
IceConnectionNumber(proxy->pmConn->iceConn));
}
else
fputc ('\n', stdout);
}
*prev_reqP = req->next;
if (req->serviceName)
free (req->serviceName);
if (req->serverAddress)
free (req->serverAddress);
if (req->hostAddress)
free (req->hostAddress);
if (req->startOptions)
free (req->startOptions);
if (req->listData)
free (req->listData);
if (req->authName)
free (req->authName);
if (req->authData)
free (req->authData);
free (req);
}
else
prev_reqP = &req->next;
req = *prev_reqP;
}
}
prevProxy = proxy;
proxy = proxy->next;
}
service = service->next;
}
}
running_proxy_list *
GetRunningProxyList (
char *serviceName, char *serverAddress)
{
proxy_service *service = FindProxyService (serviceName, False);
running_proxy **proxyList, *proxy;
running_proxy_list *runList;
int headIndex, tailIndex;
if (!service || !service->proxyCount)
return NULL;
runList = (running_proxy_list *) malloc (sizeof (running_proxy_list) +
service->proxyCount * sizeof (running_proxy *));
if (!runList)
return NULL;
runList->count = 0;
runList->current = 0;
runList->list = proxyList = (running_proxy **) (runList + 1);
proxy = service->proxyList;
headIndex = 0;
tailIndex = service->proxyCount - 1;
while (proxy)
{
server_list *server = proxy->servers;
int match = 0;
while (server)
{
if (strcmp (server->serverAddress, serverAddress) == 0)
{
match = 1;
break;
}
server = server->next;
}
if (match) {
proxyList[headIndex++] = proxy;
runList->count++;
}
else if (! proxy->refused_service) {
proxyList[tailIndex--] = proxy;
runList->count++;
}
proxy = proxy->next;
}
if (!runList->count) {
free ((char*)runList);
return NULL;
}
if (runList->count < service->proxyCount) {
while (tailIndex < service->proxyCount - 1)
proxyList[headIndex++] = proxyList[++tailIndex];
}
return runList;
}
void
FreeProxyList (running_proxy_list *list)
{
free (list);
}
Status
PushRequestorQueue (
running_proxy *proxy,
PMconn *requestor,
running_proxy_list *runList,
char *serviceName,
char *serverAddress,
char *hostAddress,
char *startOptions,
int authLen,
char *authName,
char *authData)
{
request_list *newreq = (request_list *) malloc (sizeof (request_list));
if (!newreq)
return 0;
newreq->serviceName = (char *) malloc (strlen (serviceName) + 1);
newreq->serverAddress = (char *) malloc (strlen (serverAddress) + 1);
newreq->hostAddress = (char *) malloc (strlen (hostAddress) + 1);
newreq->startOptions = (char *) malloc (strlen (startOptions) + 1);
if (authLen > 0)
{
newreq->authName = (char *) malloc (strlen (authName) + 1);
newreq->authData = (char *) malloc (authLen);
}
if (!newreq->serviceName ||
!newreq->serverAddress ||
!newreq->hostAddress ||
!newreq->startOptions ||
(authLen > 0 && (!newreq->authName || !newreq->authData)))
{
if (newreq->serviceName)
free (newreq->serviceName);
if (newreq->serverAddress)
free (newreq->serverAddress);
if (newreq->hostAddress)
free (newreq->hostAddress);
if (newreq->startOptions)
free (newreq->startOptions);
if (newreq->authName)
free (newreq->authName);
if (newreq->authData)
free (newreq->authData);
free (newreq);
return 0;
}
strcpy (newreq->serviceName, serviceName);
strcpy (newreq->serverAddress, serverAddress);
strcpy (newreq->hostAddress, hostAddress);
strcpy (newreq->startOptions, startOptions);
if (authLen > 0)
{
strcpy (newreq->authName, authName);
memcpy (newreq->authData, authData, authLen);
}
else
{
newreq->authName = newreq->authData = NULL;
}
newreq->requestor = requestor;
newreq->listData = (char *) runList;
newreq->authLen = authLen;
newreq->next = NULL;
if (proxy->requests == NULL)
proxy->requests = newreq;
else
{
request_list *p = proxy->requests;
while (p->next)
p = p->next;
p->next = newreq;
}
return 1;
}
Status
PeekRequestorQueue (
PMconn *pmConn,
PMconn **requestor,
running_proxy_list **runList,
char **serviceName,
char **serverAddress,
char **hostAddress,
char **startOptions,
int *authLen,
char **authName,
char **authData)
{
running_proxy *proxy = ProxyForPMconn (pmConn);
if (proxy && proxy->requests) {
if (requestor)
*requestor = proxy->requests->requestor;
if (runList)
*runList = (running_proxy_list *)
proxy->requests->listData;
if (serviceName)
*serviceName = proxy->requests->serviceName;
if (serverAddress)
*serverAddress = proxy->requests->serverAddress;
if (hostAddress)
*hostAddress = proxy->requests->hostAddress;
if (startOptions)
*startOptions = proxy->requests->startOptions;
if (authLen)
*authLen = proxy->requests->authLen;
if (authName)
*authName = proxy->requests->authName;
if (authData)
*authData = proxy->requests->authData;
return 1;
}
else
return 0;
}
running_proxy *
ProxyForPMconn (
PMconn *pmConn)
{
proxy_service *service = proxyServiceList;
while (service)
{
running_proxy *proxy = service->proxyList;
while (proxy)
{
if (proxy->pmConn == pmConn)
return proxy;
else
proxy = proxy->next;
}
service = service->next;
}
return NULL;
}
PMconn*
PopRequestorQueue (
PMconn *pmConn,
Bool addServer,
Bool freeProxyList)
{
running_proxy *proxy = ProxyForPMconn (pmConn);
if (proxy) {
PMconn *requestor;
server_list *server;
request_list *nextreq;
Bool newServer = False;
if (addServer) {
newServer = True;
server = proxy->servers;
while (server)
{
if (strcmp (server->serverAddress,
proxy->requests->serverAddress) == 0)
{
newServer = False;
break;
}
server = server->next;
}
if (newServer)
{
server = (server_list *) malloc (sizeof (server_list));
server->serverAddress = proxy->requests->serverAddress;
server->next = proxy->servers;
proxy->servers = server;
}
}
if (!newServer)
free (proxy->requests->serverAddress);
if (proxy->requests->serviceName)
free (proxy->requests->serviceName);
if (proxy->requests->hostAddress)
free (proxy->requests->hostAddress);
if (proxy->requests->startOptions)
free (proxy->requests->startOptions);
if (freeProxyList && proxy->requests->listData)
free (proxy->requests->listData);
if (proxy->requests->authName)
free (proxy->requests->authName);
if (proxy->requests->authData)
free (proxy->requests->authData);
requestor = proxy->requests->requestor;
nextreq = proxy->requests->next;
free (proxy->requests);
proxy->requests = nextreq;
return requestor;
}
return NULL;
}