/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- sloc_custom_status
- sloc_get_list
- sloc_config_get_list
- sloc_bcast_add
- sloc_bcast_delete
- sloc_bcast_config_add
- sloc_bcast_config_delete
- sloc_get_active_socloc
- sloc_find_first_active
- sloc_is_init
- sloc_ll_status
- sloc_sr_code
- sloc_sr_char
- sloc_client_connect
/* A communications module for the socket locate service server.
This module is used only by 'socloc' servers to talk to
other 'socloc' servers. Applies to TCP socket IPC method only.
Rick Smereka, Copyright (C) 2003.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, get a copy via the Internet at
http://gnu.org/copyleft/gpl.html or write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston,
MA 02111-1307 USA
You can contact the author via email at rsmereka@future-lab.com
This module was constructed to enable a 'socloc' server to communicate
with other 'socloc' and socket servers without using the standard 'socloc'
client API. It was found that having both client applications and
'socloc' servers using the standard 'socloc' API ('sloc.c') was
causing too many interactions. Since a specific 'socloc' server
may talk to a number of other 'socloc' servers along with any
number of socket servers, this API does not follow the model of
other Future Lab socket API's. Instead of connecting to another
server and leaving the socket open, this API performs a 'connect',
send, receive and a disconnect once per request.
Original Linux version. May/2003, Rick Smereka
Ported to 32-bit Windows, Jun/2003, Rick Smereka */
#include "stdhead.h" // standard include
#include "flsocket.h" // standard socket defines
#include "ipcomm.h" // low level socket send/receive
#include "slocsrv.h" // this module
#include "socloc.h" // global socket locator defines
#include "slconfig.h" // socket locate config management
#include "ip.h" // IP library routines
// global (to module) data
#ifdef OS_WIN32
SOCKET slclientSocket; // client socket
SOCKADDR_IN slsockClientAddr; // client address structure
LPHOSTENT lpHostEnt; // host info structure
#endif
#ifdef OS_UNIX
int slclientSocket;
struct sockaddr_in slsockClientAddr;
struct hostent *lpHostEnt;
#endif
char sloc_hostname[128]; // host name of 'socloc' server
int sloc_port = 0; // port 'socloc' is using
// private functions
static int sloc_ll_status(void);
static int sloc_sr_code(int, char *);
static int sloc_sr_char(int, char *, char *);
static int sloc_client_connect(void);
int sloc_custom_status(char *hname, int port)
{
/* Query the status of any socket server on any port.
Socket server must understand the status command
code (see 'flsocket.h'). Function returns
'SL_OK' if the server is responding, a 'socloc'
code otherwise. */
char mname[] = "sloc_custom_status";
char thost[128];
int ret, tport;
log_file_date("%s:enter", mname);
if (hname == (char *)NULL || !strlen(hname))
{
log_file_date("%s:null or empty[hname]", mname);
return(SL_INVALID_PARAMETER);
}
if (port <= 0)
{
log_file_date("%s:out of range[port]", mname);
return(SL_INVALID_PARAMETER);
}
/* save current host name and port */
strcpy(thost, sloc_hostname);
tport = sloc_port;
/* load new values */
strcpy(sloc_hostname, hname);
sloc_port = port;
/* call low level status */
if ((ret = sloc_ll_status()) != SL_OK)
{
log_file_date("%s:bad rc[%d] from sloc_ll_status", mname, ret);
strcpy(sloc_hostname, thost);
sloc_port = tport;
return(ret);
}
log_file_date("%s:normal exit[%d]", mname, ret);
strcpy(sloc_hostname, thost);
sloc_port = tport;
return(ret);
}
int sloc_get_list(char *list_out)
{
/* Get the 'socloc' list. The delimited list is
returned in 'list_out' which must already be allocated
by the caller to sufficient size. Function returns
'SL_OK' upon success, a 'socloc' code otherwise. */
char mname[] = "sloc_get_list";
int ret;
log_file_date("%s:enter", mname);
if (list_out == (char *)NULL)
{
log_file_date("%s:null[list_out]", mname);
return(SL_INVALID_PARAMETER);
}
ret = sloc_sr_char(SL_SEND_GET_LIST, (char *)NULL, list_out);
log_file_date("%s:normal exit[%d]", mname, ret);
return(ret);
}
int sloc_config_get_list(char *list_out)
{
/* Get the 'socloc' config list. The delimited list is
returned in 'list_out' which must already be allocated
by the caller to sufficient size. Function returns
'SL_OK' upon success, a 'socloc' code otherwise. */
char mname[] = "sloc_config_get_list";
int ret;
log_file_date("%s:enter", mname);
if (list_out == (char *)NULL)
{
log_file_date("%s:null[list_out]", mname);
return(SL_INVALID_PARAMETER);
}
ret = sloc_sr_char(SL_SEND_CONFIG_GET_LIST, (char *)NULL, list_out);
log_file_date("%s:normal exit[%d]", mname, ret);
return(ret);
}
int sloc_bcast_add(char *sname, char *hname, int port, char *ip_ad)
{
/* Send an add command to each known 'socloc' server.
This function should only be used by a 'socloc' server.
Note that it is not considered an error if a 'socloc'
server does not respond or responds with an error.
Function returns a 'socloc' code. */
char mname[] = "sloc_bcast_add";
char thost[128], *aentry;
int tport, nentries, i, ret;
log_file_date("%s:enter", mname);
if (sname == (char *)NULL || !strlen(sname))
{
log_file_date("%s:null or empty[sname]", mname);
return(SL_INVALID_PARAMETER);
}
if (hname == (char *)NULL || !strlen(hname))
{
log_file_date("%s:null or empty[hname]", mname);
return(SL_INVALID_PARAMETER);
}
if (port <= 0)
{
log_file_date("%s:out of range[port]", mname);
return(SL_INVALID_PARAMETER);
}
/* save current server host name and port */
strcpy(thost, sloc_hostname);
tport = sloc_port;
if ((ret = sl_config_get_nentries(&nentries)) != SL_OK)
{
log_file_date("%s:bad rc[%d] from sl_config_get_nentries", mname, ret);
return(ret);
}
log_file_date("%s:number of config entries is %d", mname, nentries);
if ((aentry = (char *)malloc(SL_MAXCOMMAND)) == (char *)NULL)
{
log_file_date("%s:alloc fail[aentry]", mname);
return(SL_MEMORY_FAIL);
}
if (ip_ad != (char *)NULL && strlen(ip_ad))
sprintf(aentry, "0 '%s' '%s' %d %s", sname, hname, port, ip_ad);
else
sprintf(aentry, "0 '%s' '%s' %d", sname, hname, port);
/* go through list of servers, sending an add command to each
with the 'orig_flag' set to a server (0) */
for(i = 1; i <= nentries; i++)
{
if ((ret = sl_config_get_nth(i, sloc_hostname, &sloc_port, (char *)NULL))
== SL_OK)
{
ret = sloc_sr_code(SL_SEND_ADD, aentry);
log_file_date("%s[%s,%d]rc=%d", mname, sloc_hostname, sloc_port, ret);
}
}
/* put back current entry */
strcpy(sloc_hostname, thost);
sloc_port = tport;
free(aentry);
log_file_date("%s:normal exit[0]", mname);
return(SL_OK);
}
int sloc_bcast_delete(int port)
{
/* Send a delete command to each known 'socloc' server.
This function should only be used by a 'socloc' server.
Note that it is not considered an error if a 'socloc'
server does not respond or responds with an error.
Function returns a 'socloc' code. */
char mname[] = "sloc_bcast_delete";
char thost[128], *aentry;
int tport, nentries, i, ret;
log_file_date("%s:enter,port=%d", mname, port);
if (port <= 0)
{
log_file_date("%s:out of range[port]", mname);
return(SL_INVALID_PARAMETER);
}
/* save current server host name and port */
strcpy(thost, sloc_hostname);
tport = sloc_port;
if ((ret = sl_config_get_nentries(&nentries)) != SL_OK)
{
log_file_date("%s:bad rc[%d] from sl_config_get_nentries", mname, ret);
return(ret);
}
log_file_date("%s:number of config entries is %d", mname, nentries);
if ((aentry = (char *)malloc(SL_MAXCOMMAND)) == (char *)NULL)
{
log_file_date("%s:alloc fail[aentry]", mname);
return(SL_MEMORY_FAIL);
}
/* indicate a server send with the initial 'orig_flag' set to zero */
sprintf(aentry, "0 %d", port);
/* go through list of servers, sending a config add command to each */
for(i = 1; i <= nentries; i++)
{
if ((ret = sl_config_get_nth(i, sloc_hostname, &sloc_port, (char *)NULL))
== SL_OK)
{
ret = sloc_sr_code(SL_SEND_DELETE, aentry);
log_file_date("%s[%s,%d]rc=%d", mname, sloc_hostname, sloc_port, ret);
}
}
/* put back current entry */
strcpy(sloc_hostname, thost);
sloc_port = tport;
free(aentry);
log_file_date("%s:normal exit[0]", mname);
return(SL_OK);
}
int sloc_bcast_config_add(char *hname, int port, char *ip_ad)
{
/* Send a config add command to each known 'socloc' server.
This function should only be used by a 'socloc' server.
Note that it is not considered an error if a 'socloc'
server does not respond or responds with an error.
Function returns a 'socloc' code. */
char mname[] = "sloc_bcast_config_add";
char thost[128], *aentry;
int tport, nentries, i, ret;
log_file_date("%s:enter", mname);
if (hname == (char *)NULL || !strlen(hname))
{
log_file_date("%s:null or empty[hname]", mname);
return(SL_INVALID_PARAMETER);
}
if (port <= 0)
{
log_file_date("%s:out of range[port]", mname);
return(SL_INVALID_PARAMETER);
}
/* save current server host name and port */
strcpy(thost, sloc_hostname);
tport = sloc_port;
if ((ret = sl_config_get_nentries(&nentries)) != SL_OK)
{
log_file_date("%s:bad rc[%d] from sl_config_get_nentries", mname, ret);
return(ret);
}
log_file_date("%s:number of config entries is %d", mname, nentries);
if ((aentry = (char *)malloc(SL_MAXCOMMAND)) == (char *)NULL)
{
log_file_date("%s:alloc fail[aentry]", mname);
return(SL_MEMORY_FAIL);
}
/* indicate a server send with the initial 'orig_flag' set to zero */
if (ip_ad != (char *)NULL && strlen(ip_ad))
sprintf(aentry, "0 '%s' %d %s", hname, port, ip_ad);
else
sprintf(aentry, "0 '%s' %d", hname, port);
/* go through list of servers, sending a config add command to each */
for(i = 1; i <= nentries; i++)
{
if ((ret = sl_config_get_nth(i, sloc_hostname, &sloc_port, (char *)NULL))
== SL_OK)
{
ret = sloc_sr_code(SL_SEND_CONFIG_ADD, aentry);
log_file_date("%s[%s,%d]rc=%d", mname, sloc_hostname, sloc_port, ret);
}
}
/* put back current entry */
strcpy(sloc_hostname, thost);
sloc_port = tport;
free(aentry);
log_file_date("%s:normal exit[0]", mname);
return(SL_OK);
}
int sloc_bcast_config_delete(int port)
{
/* Send a config delete command to each known 'socloc' server.
This function should only be used by a 'socloc' server.
Note that it is not considered an error if a 'socloc'
server does not respond or responds with an error.
Function returns a 'socloc' code. */
char mname[] = "sloc_bcast_config_delete";
char thost[128], *aentry;
int tport, nentries, i, ret;
log_file_date("%s:enter", mname);
if (port <= 0)
{
log_file_date("%s:out of range[port]", mname);
return(SL_INVALID_PARAMETER);
}
/* save current server host name and port */
strcpy(thost, sloc_hostname);
tport = sloc_port;
if ((ret = sl_config_get_nentries(&nentries)) != SL_OK)
{
log_file_date("%s:bad rc[%d] from sl_config_get_nentries", mname, ret);
return(ret);
}
log_file_date("%s:number of config entries is %d", mname, nentries);
if ((aentry = (char *)malloc(SL_MAXCOMMAND)) == (char *)NULL)
{
log_file_date("%s:alloc fail[aentry]", mname);
return(SL_MEMORY_FAIL);
}
sprintf(aentry, "0 %d", port);
/* go through list of servers, sending a config add command to each */
for(i = 1; i <= nentries; i++)
{
if ((ret = sl_config_get_nth(i, sloc_hostname, &sloc_port, (char *)NULL))
== SL_OK)
{
ret = sloc_sr_code(SL_SEND_CONFIG_DELETE, aentry);
log_file_date("%s[%s,%d]rc=%d", mname, sloc_hostname, sloc_port, ret);
}
}
/* put back current entry */
strcpy(sloc_hostname, thost);
sloc_port = tport;
free(aentry);
log_file_date("%s:normal exit[0]", mname);
return(SL_OK);
}
void sloc_get_active_socloc(char *hname, int *port)
{
/* Get and return the active 'socloc' server host name
and port number. 'hname' must be allocated by the
caller to sufficient size. */
char mname[] = "sloc_get_active_socloc";
if (hname == (char *)NULL || port == (int *)NULL)
{
log_file_date("%s:null[hname or port]", mname);
return;
}
hname[0] = EOS;
*port = 0;
if (!strlen(sloc_hostname) || sloc_port == 0)
{
log_file_date("%s:no active server", mname);
return;
}
strcpy(hname, sloc_hostname);
*port = sloc_port;
log_file_date("%s:normal exit", mname);
}
int sloc_find_first_active(void)
{
/* Traverse through the list of socket locate servers and
find the first one active. The active server host name
and port number will be loaded into the globals
'sloc_hostname' and 'sloc_port' upon success. Any entry
in the list not found to be active will be deleted. Function
returns 'SL_OK' upon success, a socket locate code
otherwise. */
char mname[] = "sloc_find_first_active";
int nentries;
int ret;
log_file_date("%s:enter", mname);
while(1)
{
if ((ret = sl_config_get_nentries(&nentries)) != SL_OK)
{
log_file_date("%s:bad rc[%d] from sl_config_get_nentries", mname, ret);
return(ret);
}
log_file_date("%s:number of config entries is %d", mname, nentries);
/* load host name and port number for this entry */
if ((ret = sl_config_get_first(sloc_hostname, &sloc_port,
(char *)NULL)) != SL_OK)
{
log_file_date("%s:bad rc[%d] from sl_config_get_first", mname, ret);
return(ret);
}
log_file_date("%s:config entry:sloc_hostname=%s,sloc_port=%d",
mname, sloc_hostname, sloc_port);
/* get status of server */
if ((ret = sloc_ll_status()) == SL_OK)
{
log_file_date("%s:exit:server %s responding", mname, sloc_hostname);
return(ret);
}
log_file_date("%s:server %s not responding", mname, sloc_hostname);
/* if not responding delete entry */
if ((ret = sl_config_delete(sloc_port)) != SL_OK)
{
log_file_date("%s:bad rc[%d] from sl_config_delete", mname, ret);
return(ret);
}
}
/* we should never get here but just in case */
sloc_hostname[0] = EOS;
sloc_port = 0;
log_file_date("%s:unanticipated wacky exit,rc=%d", mname,
SL_NO_SUCH_SOCLOC);
return(SL_NO_SUCH_SOCLOC);
}
int sloc_is_init(void)
{
/* Determine whether the 'socloc' API has been initialized.
The API is considered initialized when there is an active
host name in 'sloc_hostname' and a positive port number in
'sloc_port'. Function returns 'SL_OK' if the API has been
initialized, 'SL_NO_INIT' otherwise. */
char mname[] = "sloc_is_init";
int ret;
log_file_date("%s:enter", mname);
if (!sloc_port || sloc_hostname == (char *)NULL || !strlen(sloc_hostname))
ret = SL_NO_INIT;
else
ret = SL_OK;
log_file_date("%s:normal exit[%d]", mname, ret);
return(ret);
}
/* private functions */
static int sloc_ll_status(void)
{
/* Get the status from the current 'socloc' server.
Function returns 'SL_OK' upon success, a 'socloc'
code otherwise. */
char mname[] = "sloc_ll_status";
int ret;
log_file_date("%s:enter:host=%s,port=%d", mname, sloc_hostname,
sloc_port);
ret = sloc_sr_code(SL_SEND_STATUS, (char *)NULL);
log_file_date("%s:normal exit[%d]", mname, ret);
return(ret);
}
static int sloc_sr_code(int typ, char *parm)
{
/* Send and recveive a message to the 'socloc' server that returns
only a return code. Its ok if 'parm' is NULL or empty.
Function returns a 'socloc' code. */
char mname[] = "sloc_sr_code", *mess;
int len, full_len, ret;
/* if init has not been called, exit error */
if ((ret = sloc_is_init()) != SL_OK)
{
log_file_date("%s:no socloc server details", mname);
return(ret);
}
// connect to defined server
if ((ret = sloc_client_connect()) != SL_OK)
{
log_file_date("%s:bad rc[%d] from sloc_client_connect", mname, ret);
return(ret);
}
// estimate length and alloc send/receive buffer
len = (parm == (char *)NULL) ? 0 : strlen(parm);
full_len = len + 5;
if ((mess = (char *)malloc(full_len)) == (char *)NULL)
{
#ifdef OS_WIN32
(void)closesocket(slclientSocket);
#else
close(slclientSocket);
#endif
log_file_date("%s:alloc fail[mess]", mname);
return(SL_MEMORY_FAIL);
}
memset(mess, 0, full_len);
// format send string
if (parm == (char *)NULL || !len)
sprintf(mess, "%d", typ);
else
sprintf(mess, "%d %s", typ, parm);
// send message
if (!ipc_send(slclientSocket, mess))
{
#ifdef OS_WIN32
(void)closesocket(slclientSocket);
#else
close(slclientSocket);
#endif
log_file_date("%s:bad rc[FALSE] from ipc_send", mname);
free(mess);
return(SL_VC_ERROR);
}
memset(mess, 0, full_len);
// receive return code
if (!ipc_recv(slclientSocket, mess))
{
#ifdef OS_WIN32
(void)closesocket(slclientSocket);
#else
close(slclientSocket);
#endif
log_file_date("%s:bad rc[FALSE] from ipc_recv", mname);
free(mess);
return(SL_VC_ERROR);
}
// make sure its a number
if (!qatoi(mess, &ret))
{
#ifdef OS_WIN32
(void)closesocket(slclientSocket);
#else
close(slclientSocket);
#endif
log_file_date("%s:bad rc[FALSE] from qatoi[wrd 1]", mname);
free(mess);
return(SL_INTERNAL_ERROR);
}
free(mess);
#ifdef OS_WIN32
(void)closesocket(slclientSocket);
#else
close(slclientSocket);
#endif
return(ret);
}
static int sloc_sr_char(int typ, char *parm, char *char_out)
{
/* Send and recveive a message to the 'socloc' server that returns a
string as well as a return code. 'char_out' must already
be allocated to sufficient size for the receiving string.
Its ok if 'parm' is NULL or empty. Function returns a 'socloc' code. */
char mname[] = "sloc_sr_char", *mess, tmp[50];
int len, full_len, nwords, pos, ret;
/* if init has not been called, exit error */
if ((ret = sloc_is_init()) != SL_OK)
{
log_file_date("%s:no socloc server details", mname);
return(ret);
}
char_out[0] = EOS;
// connect to defined server
if ((ret = sloc_client_connect()) != SL_OK)
{
log_file_date("%s:bad rc[%d] from sloc_client_connect", mname, ret);
return(ret);
}
// estimate length and alloc send/receive buffer
len = (parm == (char *)NULL) ? 0 : strlen(parm);
full_len = len + 5;
if ((mess = (char *)malloc(full_len)) == (char *)NULL)
{
log_file_date("%s:alloc fail[mess]", mname);
return(SL_MEMORY_FAIL);
}
memset(mess, 0, full_len);
// format send string
if (parm == (char *)NULL || !len)
sprintf(mess, "%d", typ);
else
sprintf(mess, "%d %s", typ, parm);
// send message
if (!ipc_send(slclientSocket, mess))
{
#ifdef OS_WIN32
(void)closesocket(slclientSocket);
#else
close(slclientSocket);
#endif
log_file_date("%s:bad rc[FALSE] from ipc_send", mname);
free(mess);
return(SL_VC_ERROR);
}
free(mess);
// re-allocate 'mess' for receive buffer (max size)
if ((mess = (char *)malloc(SL_MAXCOMMAND)) == (char *)NULL)
{
#ifdef OS_WIN32
(void)closesocket(slclientSocket);
#else
close(slclientSocket);
#endif
log_file_date("%s:alloc fail[mess]", mname);
return(SL_MEMORY_FAIL);
}
memset(mess, 0, SL_MAXCOMMAND);
// receive reply
if (!ipc_recv(slclientSocket, mess))
{
#ifdef OS_WIN32
(void)closesocket(slclientSocket);
#else
close(slclientSocket);
#endif
log_file_date("%s:bad rc[FALSE] from ipc_recv", mname);
free(mess);
return(SL_VC_ERROR);
}
// s/b two words in reply
nwords = command_words(mess);
// s/b reply code in word one
if (!command_word(mess, tmp, 1))
{
#ifdef OS_WIN32
(void)closesocket(slclientSocket);
#else
close(slclientSocket);
#endif
log_file_date("%s:bad rc[FALSE] from command_word[1]", mname);
free(mess);
return(SL_INTERNAL_ERROR);
}
// make sure its a number
if (!qatoi(tmp, &ret))
{
#ifdef OS_WIN32
(void)closesocket(slclientSocket);
#else
close(slclientSocket);
#endif
log_file_date("%s:bad rc[FALSE] from qatoi[wrd 1]", mname);
free(mess);
return(SL_INTERNAL_ERROR);
}
// if reply is 'ok', load 'char_out'
if (ret == SL_OK)
{
if (nwords < 2)
{
#ifdef OS_WIN32
(void)closesocket(slclientSocket);
#else
close(slclientSocket);
#endif
log_file_date("%s:expecting at least two words in reply", mname);
free(mess);
return(SL_INTERNAL_ERROR);
}
// 'char_value' is from the end of the first word
if ((pos = command_indxword(mess, 2)) == -1)
{
#ifdef OS_WIN32
(void)closesocket(slclientSocket);
#else
close(slclientSocket);
#endif
log_file_date("%s:bad rc[-1] from command_indxword[2]", mname);
free(mess);
return(SL_INTERNAL_ERROR);
}
/* if second command word starts with quote backup one */
if (mess[pos - 1] == '\'' || mess[pos - 1] == '"')
pos -= 1;
len = strlen(mess) - pos;
strncpy(char_out, &mess[pos], len);
char_out[len] = EOS;
}
free(mess);
#ifdef OS_WIN32
(void)closesocket(slclientSocket);
#else
close(slclientSocket);
#endif
return(ret);
}
static int sloc_client_connect(void)
{
/* Connect to the 'socloc' server. An attempt to open the TCP
socket is made. The host name 'sloc_hostname' and the
TCP port 'sloc_port' are assumed to be already loaded
Function returns 'SL_OK' if a successful connection was
made, a 'socloc' code otherwise. Private function. */
char mname[] = "sloc_client_connect";
int ret;
// make sure host name and port are loaded
if ((ret = sloc_is_init()) != SL_OK)
{
log_file_date("%s:bad rc[%d] from sloc_is_init", mname, ret);
return(ret);
}
// resolve server host name
lpHostEnt = gethostbyname(sloc_hostname);
if (!lpHostEnt)
{
log_file_date("%s:bad rc[0] from gethostbyname", mname);
return(SL_VC_ERROR);
}
// create the socket
#ifdef OS_WIN32
slclientSocket = socket(PF_INET, SOCK_STREAM, DEFAULT_PROTOCOL);
#endif
#ifdef OS_UNIX
slclientSocket = socket(AF_INET, SOCK_STREAM, DEFAULT_PROTOCOL);
#endif
if (slclientSocket == INVALID_SOCKET)
{
log_file_date("%s:bad rc[INVALID_SOCKET] from socket", mname);
return(SL_VC_ERROR);
}
// load client address data
memset(&slsockClientAddr, 0, sizeof(slsockClientAddr));
slsockClientAddr.sin_family = AF_INET;
slsockClientAddr.sin_port = htons(sloc_port);
#ifdef OS_WIN32
slsockClientAddr.sin_addr = *((LPIN_ADDR)*lpHostEnt->h_addr_list);
#endif
#ifdef OS_UNIX
slsockClientAddr.sin_addr.s_addr = ((struct in_addr *)(lpHostEnt->h_addr))->s_addr;
#endif
// connect to server
#ifdef OS_WIN32
if (connect(slclientSocket, (LPSOCKADDR)&slsockClientAddr,
sizeof(slsockClientAddr)))
#endif
#ifdef OS_UNIX
if (connect(slclientSocket, (SA *)&slsockClientAddr,
sizeof(slsockClientAddr)) == SOCKET_ERROR)
#endif
{
log_file_date("%s:bad rc[SOCKET_ERROR] from connect", mname);
return(SL_VC_ERROR);
}
return(SL_OK);
}