|
|
/*************************************************************************
* Microsoft Windows NT * * * * Copyright(c) Microsoft Corp., 1994 * * * * Revision History: * * * * Jan. 23,94 Koti Created * * * * Description: * * * * This file contains the functions that actually get the LPD service * * running, and also all the functions that deal with socket interface * * * *************************************************************************/
#include "lpd.h"
typedef struct _FAMILY { int family; int socklen; HANDLE hAcceptThread; SOCKET sListener; // the socket that listens for ever
int iErrcode; } FAMILY;
FAMILY family[] = { { AF_INET, sizeof(SOCKADDR_IN), NULL }, { AF_INET6, sizeof(SOCKADDR_IN6), NULL }, };
#define NUM_FAMILIES (sizeof(family) / sizeof(FAMILY))
DWORD StartLPDFamily(int famidx) { SOCKADDR_STORAGE saiSs; INT iErrcode; BOOL fExclsv; SERVENT *pserv; DWORD dwNewThreadId; DWORD dwErrcode;
// Create the socket (which will be the listening socket)
family[famidx].sListener = socket( family[famidx].family, SOCK_STREAM, 0 );
if ( family[famidx].sListener == INVALID_SOCKET ) { iErrcode = WSAGetLastError();
LPD_DEBUG( "socket() failed\n" );
return( (DWORD)iErrcode ); }
//
// set this port to be "Exclusive" so that no other app can grab it
//
fExclsv = TRUE;
if (setsockopt( family[famidx].sListener, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (CHAR *)&fExclsv, sizeof(fExclsv) ) != 0) { LPD_DEBUG( "setsockopt SO_EXCLUSIVEADDRUSE failed\n"); }
// bind the socket to the LPD port
memset(&saiSs, 0, sizeof(saiSs));
pserv = getservbyname( "printer", "tcp" );
if ( pserv == NULL ) { SS_PORT(&saiSs) = htons( LPD_PORT ); } else { SS_PORT(&saiSs) = pserv->s_port; }
saiSs.ss_family = (short)family[famidx].family;
iErrcode = bind( family[famidx].sListener, (LPSOCKADDR)&saiSs, sizeof(saiSs) );
if ( iErrcode == SOCKET_ERROR ) {
iErrcode = WSAGetLastError();
LPD_DEBUG( "bind() failed\n" );
closesocket(family[famidx].sListener);
family[famidx].sListener = INVALID_SOCKET;
return( (DWORD)iErrcode ); }
// put the socket to listen,
// backlog should be 50 not 5, MohsinA, 07-May-97.
iErrcode = listen( family[famidx].sListener, 50 );
if ( iErrcode == SOCKET_ERROR ) { iErrcode = WSAGetLastError();
LPD_DEBUG( "listen() failed\n" );
closesocket(family[famidx].sListener);
family[famidx].sListener = INVALID_SOCKET;
return( (DWORD)iErrcode ); }
// Create the thread that keeps looping on accept
family[famidx].hAcceptThread = CreateThread( NULL, 0, LoopOnAccept, IntToPtr(famidx), 0, &dwNewThreadId );
if ( family[famidx].hAcceptThread == (HANDLE)NULL ) { dwErrcode = GetLastError();
LPD_DEBUG( "StartLPD:CreateThread() failed\n" );
closesocket(family[famidx].sListener);
family[famidx].sListener = INVALID_SOCKET;
return( dwErrcode ); }
return( 0 ); }
/*****************************************************************************
* * * StartLPD(): * * This function does everything that's needed to accept an incoming call * * (create a socket, listen, create a thread that loops on accept) * * * * Returns: * * NO_ERROR if everything went ok * * Error code (returned by the operation that failed) otherwise * * * * Parameters: * * dwArgc (IN): number of arguments passed in * * lpszArgv (IN): arguments to this function (array of null-terminated * * strings). First arg is the name of the service and the * * remaining are the ones passed by the calling process. * * (e.g. net start lpd /p:xyz) * * * * History: * * Jan.23, 94 Koti Created * * * *****************************************************************************/
DWORD StartLPD( DWORD dwArgc, LPTSTR *lpszArgv ) {
INT iErrcode, i; HANDLE hNewThread; WSADATA wsaData;
// for now, we ignore dwArgc and lpszArgv. Plan is to support
// command line (and/or registry configurable) parameters to the
// "net start lpd" command. At that time, we need to use them.
// initialize winsock dll
iErrcode = WSAStartup( MAKEWORD(WINSOCK_VER_MAJOR, WINSOCK_VER_MINOR), &wsaData ); if (iErrcode != 0) { LPD_DEBUG( "WSAStarup() failed\n" );
return( (DWORD)iErrcode ); }
// initialize families and only fail if ALL of them fail.
for (i=0; i<NUM_FAMILIES; i++) { family[i].iErrcode = StartLPDFamily(i); } if ((family[0].iErrcode != 0) && (family[1].iErrcode != 0)) { return( family[0].iErrcode ); }
// everything went fine: the LPD service is now running!
return( NO_ERROR );
} // end StartLPD()
void StopLPDFamily(INT iFamIdx) { DWORD dwResult;
if (family[iFamIdx].sListener == INVALID_SOCKET) { // Not started
return; }
SureCloseSocket( family[iFamIdx].sListener );
//
// accept() can take some time to return after the accept socket has
// been closed. wait for the accept thread to exit before continuing.
// This will prevent an access violation in the case where WSACleanup
// is called before accept() returns.
//
LPD_DEBUG( "Waiting for the accept thread to exit\n" ); dwResult = WaitForSingleObject( family[iFamIdx].hAcceptThread, INFINITE ); LPD_ASSERT( WAIT_OBJECT_0 == dwResult ); CloseHandle( family[iFamIdx].hAcceptThread ); }
/*****************************************************************************
* * * StopLPD(): * * This function stops the LPD service by closing the listener socket * * (so that new connections are not accepted), and by allowing all the * * active threads to finish their job and terminate on their own. * * * * Returns: * * None * * * * Parameters: * * None * * * * History: * * Jan.23, 94 Koti Created * * * *****************************************************************************/
VOID StopLPD( VOID ) {
BOOL fClientsConnected=FALSE; INT i;
DBG_TRACEIN( "StopLPD" );
//
// first of all, set the flag! This is the *only* place where we
// change the value, so need not worry about guarding it.
// This flag will cause all worker threads to exit.
//
fShuttingDownGLB = TRUE;
//
// stop accepting new connections,
// This will wake the accept(), and LoopOnAccept will exit.
//
for (i=0; i<NUM_FAMILIES; i++) { StopLPDFamily(i); }
EnterCriticalSection( &csConnSemGLB ); { if( Common.AliveThreads > 0 ){ fClientsConnected = TRUE; } } LeaveCriticalSection( &csConnSemGLB );
// wait here until the last thread to leave sets the event
if ( fClientsConnected ) { LPD_DEBUG( "Waiting for last worker thread to exit\n" ); WaitForSingleObject( hEventLastThreadGLB, INFINITE ); LPD_DEBUG( "Waiting for last worker thread done.\n" ); }
WSACleanup();
DBG_TRACEOUT( "StopLPD" );; return;
} // end StopLPD()
/*****************************************************************************
* * * LoopOnAccept(): * * This function is executed by the new thread that's created in StartLPD * * When a new connection request arrives, this function accepts it and * * creates a new thread which goes off and processes that connection. * * * * Returns: * * NO_ERROR (always) * * * * Parameters: * * lpArgv (IN): address family index * * * * History: * * Jan.23, 94 Koti Created * * * *****************************************************************************/
DWORD LoopOnAccept( LPVOID lpArgv ) { INT iFamIdx = (INT)(INT_PTR)lpArgv; SOCKET sNewConn; SOCKADDR_STORAGE saAddr; INT cbAddr; INT iErrcode; PSOCKCONN pscConn = NULL; PSOCKCONN pConnToFree = NULL; PSOCKCONN pPrevConn = NULL; BOOLEAN fLinkedIn=FALSE; HANDLE hNewThread; DWORD dwNewThreadId; DWORD dwErrcode; int MoreThread; COMMON_LPD local_common; int QueueTooLong;
DBG_TRACEIN( "LoopOnAccept " ); cbAddr = sizeof( saAddr );
// loop forever, trying to accept new calls
while( TRUE ) { LPD_DEBUG( "Calling accept.\n");
MoreThread = 0; hNewThread = NULL;
sNewConn = accept( family[iFamIdx].sListener, (LPSOCKADDR)&saAddr, &cbAddr );
if ( sNewConn == INVALID_SOCKET ) { iErrcode = WSAGetLastError();
LOGIT(("LoopOnAccept(): accept failed err=%d\n", iErrcode ));
if ( iErrcode == WSAEINTR ) { //
// sListener closed, it's shutdown time:
// exit loop (& thread!)
//
break; } else { // some error: ignore; go back & wait! (didn't connect anyway)
LOGIT(("LoopOnAccept(): bad accept err=%d\n", iErrcode ));
continue; } }else{ // it's a good connection
// Allocate a PSOCKCONN structure for this connection
pscConn = (PSOCKCONN)LocalAlloc( LMEM_FIXED, sizeof(SOCKCONN) );
// Create a new thread to deal with this connection
if ( pscConn != NULL ) { memset( (PCHAR)pscConn, 0, sizeof( SOCKCONN ) );
InitializeListHead( &pscConn->CFile_List ); InitializeListHead( &pscConn->DFile_List );
pscConn->sSock = sNewConn;
pscConn->fLogGenericEvent = TRUE; pscConn->dwThread = 0; // GetCurrentThreadId();
pscConn->hPrinter = (HANDLE)INVALID_HANDLE_VALUE; #ifdef PROFILING
pscConn->time_queued = time(NULL); #endif
EnterCriticalSection( &csConnSemGLB ); { Common.TotalAccepts++;
//
// scConnHeadGLB is the head and not used for jobs.
// Insertheadlist pscConn, WorkerThread will pull
// it out and process it.
//
if ((Common.QueueLength >= Common.AliveThreads) && (Common.AliveThreads < (int) dwMaxUsersGLB )) { MoreThread = (int)TRUE; }
if( Common.QueueLength < (int) MaxQueueLength ){ QueueTooLong = 0;
pscConn->pNext = scConnHeadGLB.pNext; scConnHeadGLB.pNext = pscConn; fLinkedIn = TRUE;
// = Doubly linked now, MohsinA, 28-May-97.
// pscConn->pPrev = &scConnHeadGLB;
// pscConn->pNext->pPrev = pscConn;
Common.QueueLength++; }else{ QueueTooLong = 1; MoreThread = 0; fLinkedIn = FALSE; }
assert( Common.QueueLength > 0 ); assert( Common.AliveThreads >= 0 ); assert( Common.TotalAccepts > 0 ); } LeaveCriticalSection( &csConnSemGLB );
if( MoreThread ){ hNewThread = CreateThread( NULL, 0, WorkerThread, NULL, // was pscConn
0, &dwNewThreadId );
if( hNewThread == NULL ){ LPD_DEBUG( "LoopOnAccept: CreateThread failed\n" ); } }else{ hNewThread = NULL; LOGIT(("LoopOnAccept: no new thread, dwMaxUsersGLB=%d.\n", dwMaxUsersGLB )); } } else { LPD_DEBUG( "LoopOnAccept: LocalAlloc(pscConn) failed\n" ); }
// Update the global information.
EnterCriticalSection( &csConnSemGLB ); { if( MoreThread && hNewThread ) Common.AliveThreads++; if( Common.MaxThreads < Common.AliveThreads ) Common.MaxThreads = Common.AliveThreads; if( (pscConn == NULL) || (MoreThread && ! hNewThread) || QueueTooLong ){ Common.TotalErrors++; } local_common = Common; // struct copy, for readonly.
} LeaveCriticalSection( &csConnSemGLB );
//
// Something went wrong? close the new connection, do cleanup.
// Q. What if CreateThread fails? does another thread
// picks up this job automatically?
// A. Yes, another thread will process it.
// We shouldn't even expect it to be at the head
// of the queue since we left the CS above.
//
if( (pscConn == NULL) || (MoreThread && !hNewThread ) || QueueTooLong ){ dwErrcode = GetLastError();
pConnToFree = NULL;
if (!fLinkedIn) { pConnToFree = pscConn; }
//
// we had already linked it in: try to find it first
//
else { EnterCriticalSection( &csConnSemGLB );
// if there is no other thread alive and if we hit an error
if( pscConn && ( Common.AliveThreads == 0 ) ) { pPrevConn = &scConnHeadGLB; pConnToFree = scConnHeadGLB.pNext;
while (pConnToFree) { if (pConnToFree == pscConn) { pPrevConn->pNext = pConnToFree->pNext; break; }
pPrevConn = pConnToFree; pConnToFree = pConnToFree->pNext; } } LeaveCriticalSection( &csConnSemGLB ); }
if (pConnToFree) { LocalFree( pConnToFree ); pscConn = NULL; SureCloseSocket( sNewConn ); }
LpdReportEvent( LPDLOG_OUT_OF_RESOURCES, 0, NULL, 0 );
}else{ #ifdef PROFILING
LOGIT(("PROFILING: LoopOnAccept:\n" " QueueLength=%d, MaxQueueLength=%d,\n" " AliveThreads=%d, TotalAccepts=%d, TotalErrors=%d\n" , local_common.QueueLength, MaxQueueLength, local_common.AliveThreads, local_common.TotalAccepts, local_common.TotalErrors )); #endif
}
if( hNewThread ){ CloseHandle( hNewThread ); } }
} // while( TRUE )
// ====================================================================
// we reach here only when shutdown is happening. The thread exits here.
DBG_TRACEOUT( "LoopOnAccept exit." ); return NO_ERROR;
} // end LoopOnAccept()
/*****************************************************************************
* * * SureCloseSocket(): * * This function closes a given socket. It first attempts a graceful * * close. If that fails for some reason, then it does a "hard" close * * * * Returns: * * Nothing * * * * Parameters: * * sSockToClose (IN): socket descriptor of the socket to close * * * * History: * * Jan.23, 94 Koti Created * * * *****************************************************************************/
VOID SureCloseSocket( SOCKET sSockToClose ) {
LINGER lLinger;
if (sSockToClose == INVALID_SOCKET) { LPD_DEBUG( "SureCloseSocket: bad socket\n" );
return; }
// try to do a graceful close
if ( closesocket(sSockToClose) == 0 ) { return; }
//for some reason, we couldn't close the socket: do a "hard" close now
LPD_DEBUG( "SureCloseSocket: graceful close did not work; doing hard close\n" );
lLinger.l_onoff = 1; // non-zero integer to say SO_LINGER
lLinger.l_linger = 0; // timeout=0 seconds to say "hard" close
// don't bother to check return code: can't do much anyway!
setsockopt( sSockToClose, SOL_SOCKET, SO_LINGER, (CHAR *)&lLinger, sizeof(lLinger) );
closesocket( sSockToClose );
} // end SureCloseSocket()
/*****************************************************************************
* * * ReplyToClient(): * * This function sends an ACK or a NAK to the LPR client * * * * Returns: * * NO_ERROR if reply sent * * Errorcode if something didn't go well * * * * Parameters: * * pscConn (IN): PSOCKCONN structure for this connection * * wResponse (IN): what needs to be sent - ACK or NAK * * * * History: * * Jan.24, 94 Koti Created * * * *****************************************************************************/
DWORD ReplyToClient( PSOCKCONN pscConn, WORD wResponse ) {
// we will always send only one byte in this function!
CHAR szSndBuf[2]; INT iErrcode;
szSndBuf[0] = (CHAR)wResponse; // ACK or NAK
iErrcode = send( pscConn->sSock, szSndBuf, 1, 0 );
if ( iErrcode == 1 ) { return( NO_ERROR ); }
if ( iErrcode == SOCKET_ERROR ) { LPD_DEBUG( "send() failed in ReplyToClient()\n" ); }
return( iErrcode );
} // end ReplyToClient()
/*****************************************************************************
* * * GetCmdFromClient(): * * This function reads a command sent by the LPR client (keeps reading * * until it finds '\n' (LF) in the stream, since every command ends with * * a LF). It allocates memory for the command. * * * * Returns: * * NO_ERROR if everything went ok * * Errorcode if something goes wrong (e.g. connection goes away etc.) * * * * Parameters: * * pscConn (IN-OUT): PSOCKCONN structure for this connection * * * * History: * * Jan.24, 94 Koti Created * * * *****************************************************************************/
DWORD GetCmdFromClient( PSOCKCONN pscConn ) {
INT cbBytesRead; INT cbBytesReadSoFar; INT cbBytesToRead; INT cbCmdLen; INT i; BOOL fCompleteCmd=FALSE; CHAR szCmdBuf[500]; PCHAR pchAllocedBuf=NULL; PCHAR pchNewAllocedBuf=NULL; SOCKET sDestSock; DWORD dwErrcode = SOCKET_ERROR;
int rdready; struct fd_set rdsocks; struct timeval timeo = { dwRecvTimeout, 0 };
cbCmdLen = 0;
cbBytesReadSoFar = 0;
sDestSock = pscConn->sSock;
// allocate a 1 byte buffer, so that we can use reallocate in a loop
pchAllocedBuf = (PCHAR)LocalAlloc( LMEM_FIXED, 1 );
if ( pchAllocedBuf == NULL ) { LPD_DEBUG( "First LocalAlloc failed in GetCmdFromClient()\n" );
goto GetCmdFromClient_BAIL; }
// Keep reading in a loop until we receive one complete command
// (with rfc1179, we shouldn't get more bytes than one command,
// though less than one command is possible)
//
// What if the client never sends nor closes? we never Timeout?
// We loose a worker thread - MohsinA, 01-May-97.
//
do {
FD_ZERO(&rdsocks); FD_SET(sDestSock, &rdsocks); rdready = select( 1, &rdsocks, 0, 0, &timeo);
if( rdready == 0 ) { LOGIT(("GetCmdFromClient: select timeout.\n")); goto GetCmdFromClient_BAIL; }else if( rdready == SOCKET_ERROR ){ LOGIT(("GetCmdFromClient: select error %d.\n", GetLastError())); goto GetCmdFromClient_BAIL; }
cbBytesRead = recv( sDestSock, szCmdBuf, sizeof(szCmdBuf), 0 );
if ( cbBytesRead <= 0 ) { if ( pchAllocedBuf != NULL ) { LocalFree( pchAllocedBuf ); } return CONNECTION_CLOSED; }
cbBytesToRead = cbBytesRead;
// see if we have received one complete command
for( i=0; i<cbBytesRead; i++) { if ( szCmdBuf[i] == LF ) { fCompleteCmd = TRUE;
cbCmdLen = (i+1) + (cbBytesReadSoFar);
cbBytesToRead = (i+1);
break; } }
// our needs are now bigger: reallocate memory
// alloc 1 more for NULL byte
pchNewAllocedBuf = (PCHAR)LocalReAlloc (pchAllocedBuf, cbBytesToRead+cbBytesReadSoFar + 1, LMEM_MOVEABLE); if (pchNewAllocedBuf == NULL) { LPD_DEBUG( "Second LocalAlloc failed in GetCmdFromClient()\n" ); goto GetCmdFromClient_BAIL; } pchAllocedBuf = pchNewAllocedBuf; pchNewAllocedBuf = NULL;
// now copy those bytes into our buffer
strncpy( (pchAllocedBuf+cbBytesReadSoFar), szCmdBuf, cbBytesToRead );
cbBytesReadSoFar += cbBytesRead;
// if some bad implementation of LPR fails to follow spec and
// never puts LF, then we don't want to be stuck here forever!
if ( cbBytesReadSoFar > LPD_MAX_COMMAND_LEN ) { LPD_DEBUG( "GetCmdFromClient(): command len exceeds our max\n" );
goto GetCmdFromClient_BAIL; }
} while( (!fCompleteCmd) || (cbBytesReadSoFar < cbCmdLen) );
pchAllocedBuf[cbCmdLen] = '\0';
pscConn->pchCommand = pchAllocedBuf;
pscConn->cbCommandLen = cbCmdLen;
return( NO_ERROR );
//
// if we reach here, something went wrong: return NULL and
// the caller will understand!
//
GetCmdFromClient_BAIL:
LOGIT(("GetCmdFromClient: failed, err=%d\n", GetLastError() ));
if ( pchAllocedBuf != NULL ) { LocalFree( pchAllocedBuf ); }
return dwErrcode;
}
/*****************************************************************************
* * * ReadData(): * * This function reads the specified number of bytes into the given * * buffer from the given socket. This function blocks until all the * * required data is available (or error occurs). * * * * Returns: * * NO_ERROR if everything went ok * * Errorcode if something goes wrong (e.g. connection goes away etc.) * * * * Parameters: * * sDestSock (IN): socket from which to read or receive data * * pchBuf (OUT): buffer into which to store the data * * cbBytesToRead (IN): how many bytes to read * * * * History: * * Jan.24, 94 Koti Created * * * *****************************************************************************/
DWORD ReadData( SOCKET sDestSock, PCHAR pchBuf, DWORD cbBytesToRead ) {
DWORD cbBytesExpctd; DWORD cbBytesRead;
int rdready; struct fd_set rdsocks; struct timeval timeo = { dwRecvTimeout, 0 };
cbBytesExpctd = cbBytesToRead;
do{
FD_ZERO(&rdsocks); FD_SET(sDestSock, &rdsocks); rdready = select( 1, &rdsocks, 0, 0, &timeo);
if( rdready == 0 ){ LOGIT(("ReadData: select timeout.\n")); goto ReadData_Bail; }else if( rdready == SOCKET_ERROR ){ LOGIT(("ReadData: select error %d.\n", GetLastError())); goto ReadData_Bail; }
cbBytesRead = recv( sDestSock, pchBuf, cbBytesExpctd, 0 );
if ( (cbBytesRead == SOCKET_ERROR) || (cbBytesRead == 0) ) { goto ReadData_Bail; }
cbBytesExpctd -= cbBytesRead; pchBuf += cbBytesRead;
} while( cbBytesExpctd != 0 );
return( NO_ERROR );
ReadData_Bail:
LOGIT(("ReadData: failed %d\n", GetLastError() )); return LPDERR_NORESPONSE;
} // end ReadData()
// ========================================================================
// We sleep while file is downloaded from the socket.
// Performance fix, MohsinA, 23-Apr-97.
//
DWORD ReadDataEx( SOCKET sDestSock, PCHAR pchBuf, DWORD cbBytesToRead ) { BOOL ok; DWORD err; DWORD BytesRead = 0; OVERLAPPED ol = { 0,0,0,0,0 };
while( cbBytesToRead ){
ok = ReadFile( (HANDLE) sDestSock, pchBuf, cbBytesToRead, &BytesRead, &ol );
if( ok ){ cbBytesToRead -= BytesRead; pchBuf += BytesRead; continue; }
// Else ReadFile is pending?
err = GetLastError(); switch( err ){ case ERROR_IO_PENDING : ok = GetOverlappedResult( (HANDLE) sDestSock, &ol, &BytesRead, TRUE ); if( ! ok ){ err = GetLastError(); LOGIT(("lpd:ReadDataEx:GetOverlappedResult failed %d.\n", err )); return LPDERR_NORESPONSE; } break; case ERROR_HANDLE_EOF : return NO_ERROR; default: LOGIT(("lpd:ReadDataEx:ReadFileEx failed %d.\n", err )); return LPDERR_NORESPONSE; }
} // while.
return( NO_ERROR ); }
/*****************************************************************************
* * * SendData(): * * This function attempts to send the specified number of bytes over the * * given socket. The function blocks until send() returns. * * * * Returns: * * NO_ERROR if everything went ok * * Errorcode if data couldn't be sent (e.g. connection goes away etc.) * * * * Parameters: * * sDestSock (IN): socket over which to send data * * pchBuf (IN): buffer containing data * * cbBytesToSend (IN): how many bytes to send * * * * History: * * Jan.24, 94 Koti Created * * * *****************************************************************************/
DWORD SendData( SOCKET sDestSock, PCHAR pchBuf, DWORD cbBytesToSend ) {
INT iErrcode;
iErrcode = send( sDestSock, pchBuf, cbBytesToSend, 0 );
if ( iErrcode == SOCKET_ERROR ) { LPD_DEBUG( "send() failed in SendData()\n" ); }
return( (DWORD)iErrcode );
} // end SendData()
/*****************************************************************************
* * * GetClientInfo(); * * This function retrieves info about the client (for now, only the IP * * address). This info is used during logging. * * * * Returns: * * Nothing * * Parameters: * * pscConn (IN-OUT): PSOCKCONN structure for this connection * * * * History: * * Jan.24, 94 Koti Created * * * *****************************************************************************/
VOID GetClientInfo( PSOCKCONN pscConn ) {
INT iErrcode; INT iLen, iLen2; SOCKADDR_STORAGE saName;
iLen = sizeof(saName);
iErrcode = getpeername( pscConn->sSock, (SOCKADDR *)&saName, &iLen );
if ( iErrcode == 0 ) { iLen2 = sizeof(pscConn->szIPAddr); SS_PORT(&saName) = 0; iErrcode = WSAAddressToString((SOCKADDR*)&saName, iLen, NULL, pscConn->szIPAddr, &iLen2); }
if (iErrcode == SOCKET_ERROR) { LPD_DEBUG( "GetClientInfo(): couldn't retrieve ip address!\n" );
strcpy( pscConn->szIPAddr, GETSTRING( LPD_ERMSG_NO_IPADDR) );
return; }
LOGTIME; LOGIT(("GetClientInfo: %s:%d\n", pscConn->szIPAddr, htons(SS_PORT(&saName)) ));
} // end GetClientInfo()
/*****************************************************************************
* * * GetServerInfo(); * * This function retrieves info about the Server (for now, only the IP * * address). This info is used during logging. * * * * Returns: * * Nothing * * Parameters: * * pscConn (IN-OUT): PSOCKCONN structure for this connection * * * * History: From Albert Ting, Printer Group, 4-Mar-97. * * MohsinA. * *****************************************************************************/
VOID GetServerInfo( PSOCKCONN pscConn ) {
INT iErrcode; INT iLen, iLen2; SOCKADDR_STORAGE saName;
iLen = sizeof(saName);
iErrcode = getsockname( pscConn->sSock, (SOCKADDR *)&saName, &iLen );
if ( iErrcode == 0 ){ iLen2 = sizeof(pscConn->szServerIPAddr); SS_PORT(&saName) = 0; iErrcode = WSAAddressToString((SOCKADDR*)&saName, iLen, NULL, pscConn->szServerIPAddr, &iLen2); }
if (iErrcode == SOCKET_ERROR){ LPD_DEBUG( "GetServerInfo(): couldn't retrieve ip address!\n" ); strcpy( pscConn->szServerIPAddr, GETSTRING( LPD_ERMSG_NO_IPADDR) ); return; }
} // end GetServerInfo()
|