зеркало из https://github.com/mozilla/pjs.git
840 строки
20 KiB
C
840 строки
20 KiB
C
/*
|
|
* The contents of this file are subject to the Netscape Public License
|
|
* Version 1.0 (the "License"); you may not use this file except in compliance
|
|
* with the License. You may obtain a copy of the License at
|
|
* http://www.mozilla.org/NPL/.
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
* for the specific language governing rights and limitations under the License.
|
|
*
|
|
* The Original Code is the Netscape Messaging Access SDK Version 3.5 code,
|
|
* released on or about June 15, 1998.
|
|
*
|
|
* The Initial Developer of the Original Code is Netscape Communications
|
|
* Corporation. Portions created by Netscape are Copyright (C) 1998 Netscape
|
|
* Communications Corporation. All Rights Reserved.
|
|
*
|
|
* Contributor(s): ______________________________________.
|
|
*/
|
|
|
|
/*
|
|
* Copyright (c) 1997 and 1998 Netscape Communications Corporation
|
|
* (http://home.netscape.com/misc/trademarks.html)
|
|
*/
|
|
|
|
/*
|
|
* nsio.c
|
|
* @author derekt@netscape.com
|
|
* @version 1.0
|
|
*/
|
|
|
|
#include "nsmail.h"
|
|
#include "nsio.h"
|
|
#include "nssocket.h"
|
|
|
|
#include <string.h>
|
|
#include <malloc.h>
|
|
#include <ctype.h>
|
|
#include <stdio.h>
|
|
|
|
/* Internal functions not to be used directly. */
|
|
int IO_checkTimeout( IO_t * in_pIO );
|
|
void IO_resetFunctions( IO_t * in_pIO );
|
|
int UpdateBuffer( IO_t * in_pIO );
|
|
|
|
/* Initalize the IO structure. */
|
|
int IO_initialize( IO_t * in_pIO,
|
|
unsigned int in_readBufferLimit,
|
|
unsigned int in_writeBufferLimit )
|
|
{
|
|
/*
|
|
* Parameter validation.
|
|
*/
|
|
|
|
if ( in_pIO == NULL ||
|
|
in_pIO->readBuffer != NULL ||
|
|
in_pIO->writeBuffer != NULL )
|
|
{
|
|
return NSMAIL_ERR_INVALIDPARAM;
|
|
}
|
|
|
|
if ( in_readBufferLimit == 0 )
|
|
{
|
|
in_pIO->readBufferLimit = DEFAULT_BUFFER_LENGTH;
|
|
}
|
|
else
|
|
{
|
|
in_pIO->readBufferLimit = in_readBufferLimit;
|
|
}
|
|
|
|
if ( in_writeBufferLimit == 0 )
|
|
{
|
|
in_pIO->writeBufferLimit = DEFAULT_BUFFER_LENGTH;
|
|
}
|
|
else
|
|
{
|
|
in_pIO->writeBufferLimit = in_writeBufferLimit;
|
|
}
|
|
|
|
/*
|
|
* Set the socket descriptor to an invalid value to identify a
|
|
* disconnected state.
|
|
*/
|
|
|
|
in_pIO->socket = -1;
|
|
|
|
/*
|
|
* Initialize the read buffer.
|
|
*/
|
|
|
|
in_pIO->readBuffer = (char*)malloc( in_pIO->readBufferLimit * sizeof( char ) );
|
|
if ( in_pIO->readBuffer == NULL )
|
|
{
|
|
return NSMAIL_ERR_OUTOFMEMORY;
|
|
}
|
|
memset(in_pIO->readBuffer, 0, in_pIO->readBufferLimit * sizeof( char ) );
|
|
|
|
/*
|
|
* Initialize the write buffer.
|
|
*/
|
|
|
|
in_pIO->writeBuffer = (char*)malloc( in_pIO->writeBufferLimit * sizeof( char ) );
|
|
if ( in_pIO->writeBuffer == NULL )
|
|
{
|
|
return NSMAIL_ERR_OUTOFMEMORY;
|
|
}
|
|
|
|
memset(in_pIO->writeBuffer, 0, in_pIO->writeBufferLimit * sizeof( char ) );
|
|
|
|
/* Set the current size of the write buffer. */
|
|
in_pIO->writeBufferSize = 0;
|
|
|
|
/* Set the current size of the read buffer. */
|
|
in_pIO->readBufferSize = 0;
|
|
|
|
/* Set the IO function pointers. */
|
|
IO_resetFunctions( in_pIO );
|
|
|
|
/* Set the default timeout value. */
|
|
return IO_setTimeout( in_pIO, -1 );
|
|
}
|
|
|
|
/* Free the IO structure. */
|
|
void IO_free( IO_t * in_pIO )
|
|
{
|
|
if ( in_pIO == NULL )
|
|
{
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Reset the data members.
|
|
*/
|
|
|
|
if ( in_pIO->readBuffer != NULL )
|
|
{
|
|
free( in_pIO->readBuffer );
|
|
in_pIO->readBuffer = NULL;
|
|
}
|
|
|
|
if ( in_pIO->writeBuffer != NULL )
|
|
{
|
|
free( in_pIO->writeBuffer );
|
|
in_pIO->writeBuffer = NULL;
|
|
}
|
|
|
|
/*
|
|
* Terminate the socket session.
|
|
*/
|
|
|
|
NSSock_Terminate();
|
|
}
|
|
|
|
/* Connect to the specified server with the specified port. */
|
|
int IO_connect( IO_t * in_pIO, const char * in_szServer, unsigned short in_nPort )
|
|
{
|
|
struct sockaddr_in l_hostInetAddr;
|
|
LinkedList_t * l_addressList;
|
|
LinkedList_t * l_tempList;
|
|
|
|
int fHostIsIPAddr;
|
|
int dotCount = 0;
|
|
int i;
|
|
|
|
/*
|
|
* Parameter validation.
|
|
*/
|
|
|
|
if ( in_pIO == NULL || in_szServer == NULL )
|
|
{
|
|
return NSMAIL_ERR_INVALIDPARAM;
|
|
}
|
|
|
|
if ( in_pIO->socket > 0 )
|
|
{
|
|
return NSMAIL_ERR_ALREADYCONNECTED;
|
|
}
|
|
|
|
/*
|
|
* Initialize the socket session.
|
|
*/
|
|
|
|
NSSock_Initialize();
|
|
|
|
/*
|
|
* Create a handle to the new socket.
|
|
*/
|
|
|
|
in_pIO->socket = in_pIO->ioFunctions.liof_socket( AF_INET, SOCK_STREAM, 0 );
|
|
|
|
if ( in_pIO->socket < 0 )
|
|
{
|
|
return NSMAIL_ERR_IO_SOCKET;
|
|
}
|
|
|
|
/* initialize the address structures */
|
|
memset (&l_hostInetAddr, 0, sizeof(l_hostInetAddr));
|
|
|
|
l_hostInetAddr.sin_family = AF_INET;
|
|
l_hostInetAddr.sin_port = htons(in_nPort);
|
|
|
|
/*
|
|
* Determine if a host name or IP address was specified. Assume
|
|
* it is, then see if we can find something that means it isn't.
|
|
* (The test below is not very careful, it should verify there
|
|
* are numbers between the dots, and the numbers are less than 256.)
|
|
*/
|
|
fHostIsIPAddr = 1;
|
|
for (i=0; i<strlen(in_szServer); ++i) {
|
|
if (in_szServer[i] == '.') {
|
|
++dotCount;
|
|
}
|
|
else if (!isdigit(in_szServer[i])) {
|
|
fHostIsIPAddr = 0;
|
|
break;
|
|
}
|
|
}
|
|
if (dotCount != 3) {
|
|
fHostIsIPAddr = 0;
|
|
}
|
|
|
|
if ( fHostIsIPAddr )
|
|
{
|
|
l_hostInetAddr.sin_addr.s_addr = inet_addr( (char *)in_szServer );
|
|
|
|
if ( in_pIO->ioFunctions.liof_connect(
|
|
in_pIO->socket,
|
|
(const struct sockaddr *)&l_hostInetAddr,
|
|
in_nPort ) != FALSE )
|
|
{
|
|
return NSMAIL_OK;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
l_addressList = NSSock_GetHostByName( in_szServer );
|
|
while ( l_addressList != NULL )
|
|
{
|
|
if ( ( l_hostInetAddr.sin_addr.s_addr = inet_addr(l_addressList->pData) ) != 0 )
|
|
{
|
|
if ( in_pIO->ioFunctions.liof_connect(
|
|
in_pIO->socket,
|
|
(const struct sockaddr *)&l_hostInetAddr,
|
|
in_nPort ) != FALSE )
|
|
{
|
|
while ( l_addressList != NULL )
|
|
{
|
|
free( l_addressList->pData );
|
|
l_tempList = l_addressList;
|
|
l_addressList = l_tempList->next;
|
|
free( l_tempList );
|
|
}
|
|
return NSMAIL_OK;
|
|
}
|
|
}
|
|
free( l_addressList->pData );
|
|
l_tempList = l_addressList;
|
|
l_addressList = l_tempList->next;
|
|
free( l_tempList );
|
|
}
|
|
}
|
|
|
|
in_pIO->socket = -1;
|
|
return NSMAIL_ERR_IO_CONNECT;
|
|
}
|
|
|
|
/* Disconnect from the server. */
|
|
int IO_disconnect( IO_t * in_pIO )
|
|
{
|
|
/*
|
|
* Parameter validation.
|
|
*/
|
|
|
|
if ( in_pIO == NULL )
|
|
{
|
|
return NSMAIL_ERR_INVALIDPARAM;
|
|
}
|
|
|
|
if ( in_pIO->socket < 0 )
|
|
{
|
|
return NSMAIL_ERR_NOTCONNECTED;
|
|
}
|
|
|
|
/*
|
|
* Close the socket.
|
|
*/
|
|
|
|
if ( in_pIO->ioFunctions.liof_close( in_pIO->socket ) == FALSE )
|
|
{
|
|
in_pIO->socket = -1;
|
|
return NSMAIL_ERR_IO_CLOSE;
|
|
}
|
|
|
|
in_pIO->socket = -1;
|
|
return NSMAIL_OK;
|
|
}
|
|
|
|
/*Send data to the server appending the \r\n and optionally flushing.*/
|
|
int IO_send( IO_t * in_pIO, const char * in_data, boolean in_bufferData )
|
|
{
|
|
int l_nReturn;
|
|
|
|
l_nReturn = IO_write( in_pIO, in_data, strlen(in_data) );
|
|
|
|
if ( l_nReturn != NSMAIL_OK )
|
|
{
|
|
return l_nReturn;
|
|
}
|
|
|
|
l_nReturn = IO_write( in_pIO, eoline, 2 );
|
|
|
|
if ( l_nReturn != NSMAIL_OK )
|
|
{
|
|
return l_nReturn;
|
|
}
|
|
|
|
if ( in_bufferData == FALSE )
|
|
{
|
|
l_nReturn = IO_flush( in_pIO );
|
|
|
|
if ( l_nReturn != NSMAIL_OK )
|
|
{
|
|
return l_nReturn;
|
|
}
|
|
}
|
|
|
|
return NSMAIL_OK;
|
|
}
|
|
|
|
/* Write operation to the buffered socket. */
|
|
int IO_write( IO_t * in_pIO, const char * in_data, unsigned int in_length )
|
|
{
|
|
int l_nReturn;
|
|
|
|
/* Parameter validation.*/
|
|
if ( in_pIO == NULL || in_data == NULL )
|
|
{
|
|
return NSMAIL_ERR_INVALIDPARAM;
|
|
}
|
|
|
|
if ( in_pIO->socket < 0 )
|
|
{
|
|
return NSMAIL_ERR_NOTCONNECTED;
|
|
}
|
|
|
|
/* Fill the buffer and send the data if it is full. */
|
|
if ( in_pIO->writeBufferSize + in_length < in_pIO->writeBufferLimit )
|
|
{
|
|
memcpy( &(in_pIO->writeBuffer[in_pIO->writeBufferSize]),
|
|
in_data,
|
|
in_length );
|
|
|
|
in_pIO->writeBufferSize += in_length;
|
|
}
|
|
else
|
|
{
|
|
l_nReturn = IO_flush( in_pIO );
|
|
|
|
if ( l_nReturn != NSMAIL_OK )
|
|
{
|
|
return l_nReturn;
|
|
}
|
|
|
|
if ( in_length < in_pIO->writeBufferLimit )
|
|
{
|
|
memcpy( in_pIO->writeBuffer, in_data, in_length );
|
|
in_pIO->writeBufferSize = in_length;
|
|
}
|
|
else
|
|
{
|
|
if ( in_pIO->ioFunctions.liof_write( in_pIO->socket,
|
|
(char*)in_data,
|
|
in_length ) == FALSE )
|
|
{
|
|
return NSMAIL_ERR_IO_WRITE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return NSMAIL_OK;
|
|
}
|
|
|
|
int IO_writeByte( IO_t * in_pIO, const char in_byte )
|
|
{
|
|
int l_nReturn;
|
|
|
|
/* Parameter validation */
|
|
if ( in_pIO == NULL )
|
|
{
|
|
return NSMAIL_ERR_INVALIDPARAM;
|
|
}
|
|
|
|
if ( in_pIO->socket < 0 )
|
|
{
|
|
return NSMAIL_ERR_NOTCONNECTED;
|
|
}
|
|
|
|
/*
|
|
* Fill the buffer and send the data if it is full.
|
|
*/
|
|
|
|
if ( in_pIO->writeBufferSize + 1 < in_pIO->writeBufferLimit )
|
|
{
|
|
in_pIO->writeBuffer[(in_pIO->writeBufferSize)++] = in_byte;
|
|
}
|
|
else
|
|
{
|
|
l_nReturn = IO_flush( in_pIO );
|
|
|
|
if ( l_nReturn != NSMAIL_OK )
|
|
{
|
|
return l_nReturn;
|
|
}
|
|
|
|
in_pIO->writeBuffer[(in_pIO->writeBufferSize)++] = in_byte;
|
|
}
|
|
|
|
return NSMAIL_OK;
|
|
}
|
|
|
|
int IO_flush( IO_t * in_pIO )
|
|
{
|
|
/* Parameter validation */
|
|
if ( in_pIO == NULL || in_pIO->writeBuffer == NULL )
|
|
{
|
|
return NSMAIL_ERR_INVALIDPARAM;
|
|
}
|
|
|
|
if ( in_pIO->socket < 0 )
|
|
{
|
|
return NSMAIL_ERR_NOTCONNECTED;
|
|
}
|
|
|
|
/* Send the data and verify that it was sent ok. */
|
|
if ( in_pIO->writeBufferSize > 0 )
|
|
{
|
|
if ( in_pIO->ioFunctions.liof_write( in_pIO->socket,
|
|
(char*)in_pIO->writeBuffer,
|
|
in_pIO->writeBufferSize ) == FALSE )
|
|
{
|
|
return NSMAIL_ERR_IO_WRITE;
|
|
}
|
|
|
|
memset( in_pIO->writeBuffer, 0, in_pIO->writeBufferLimit );
|
|
in_pIO->writeBufferSize = 0;
|
|
}
|
|
|
|
return NSMAIL_OK;
|
|
}
|
|
|
|
|
|
/**
|
|
* Read in in_size bytes into out_response
|
|
* @param in_pIO The IO structure
|
|
* @param out_ppResponse The memory to store the data in
|
|
* @param in_size The amount of data requested
|
|
& @param out_bytesRead The total number of bytes read
|
|
*/
|
|
int IO_read( IO_t * in_pIO, char * out_response, int in_size, int * out_bytesRead )
|
|
{
|
|
int l_returnCode;
|
|
int l_bytesRead = 0;
|
|
int l_bytesToRead = 0;
|
|
int l_offset = 0;
|
|
|
|
/* Parameter validation. */
|
|
if ((in_pIO == NULL) || (out_response == NULL) ||
|
|
(in_size < 1) || (out_bytesRead == NULL))
|
|
{
|
|
return NSMAIL_ERR_INVALIDPARAM;
|
|
}
|
|
|
|
/* Make sure the IO buffer is not empty */
|
|
if ( in_pIO->readBufferSize == 0 )
|
|
{
|
|
l_returnCode = UpdateBuffer( in_pIO );
|
|
|
|
if ( l_returnCode != NSMAIL_OK )
|
|
{
|
|
return l_returnCode;
|
|
}
|
|
}
|
|
|
|
|
|
/* Read in_size bytes */
|
|
while ( l_bytesRead < in_size )
|
|
{
|
|
/* Determine amount of data to read in from the IO buffer */
|
|
if( (in_pIO->readBufferSize + l_bytesRead) <= in_size)
|
|
{
|
|
l_bytesToRead = in_pIO->readBufferSize;
|
|
}
|
|
else
|
|
{
|
|
l_bytesToRead = in_size - l_bytesRead;
|
|
}
|
|
|
|
memcpy(out_response + l_bytesRead, in_pIO->readBuffer, l_bytesToRead);
|
|
in_pIO->readBufferSize -= l_bytesToRead;
|
|
l_bytesRead += l_bytesToRead;
|
|
l_offset += l_bytesToRead;
|
|
|
|
/* Make sure the IO buffer is not empty */
|
|
if ( in_pIO->readBufferSize == 0 )
|
|
{
|
|
l_returnCode = UpdateBuffer( in_pIO );
|
|
if ( l_returnCode != NSMAIL_OK )
|
|
{
|
|
return l_returnCode;
|
|
}
|
|
l_offset = 0;
|
|
}
|
|
}
|
|
|
|
/* Move the rest of the buffer to the beginning of the buffer. */
|
|
memcpy( in_pIO->readBuffer, (&in_pIO->readBuffer[l_offset]), in_pIO->readBufferSize );
|
|
(*out_bytesRead) = l_bytesRead;
|
|
|
|
return NSMAIL_OK;;
|
|
}
|
|
|
|
/* Reads a line from the socket. */
|
|
int IO_readLine( IO_t * in_pIO, char * out_response, int in_maxLength )
|
|
{
|
|
int l_returnCode;
|
|
unsigned int offset = 0;
|
|
|
|
/* Parameter validation. */
|
|
if ( in_pIO == NULL || out_response == NULL || out_response == NULL )
|
|
{
|
|
return NSMAIL_ERR_INVALIDPARAM;
|
|
}
|
|
|
|
if ( in_pIO->socket < 0 )
|
|
{
|
|
return NSMAIL_ERR_NOTCONNECTED;
|
|
}
|
|
|
|
if ( in_pIO->readBufferSize == 0 )
|
|
{
|
|
l_returnCode = UpdateBuffer( in_pIO );
|
|
|
|
if ( l_returnCode != NSMAIL_OK )
|
|
{
|
|
return l_returnCode;
|
|
}
|
|
}
|
|
|
|
/* Read byte by byte looking for the newline character. */
|
|
while ( in_pIO->readBuffer[offset] != '\n' )
|
|
{
|
|
offset++;
|
|
|
|
if ( offset == in_pIO->readBufferSize )
|
|
{
|
|
if ( offset == in_pIO->readBufferLimit )
|
|
{
|
|
return NSMAIL_ERR_UNEXPECTED;
|
|
}
|
|
|
|
l_returnCode = UpdateBuffer( in_pIO );
|
|
|
|
if ( l_returnCode != NSMAIL_OK )
|
|
{
|
|
return l_returnCode;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( offset > in_maxLength )
|
|
{
|
|
return NSMAIL_ERR_UNEXPECTED;
|
|
}
|
|
|
|
/* Copy the line into the buffer. */
|
|
memcpy( out_response, in_pIO->readBuffer, offset + 1 );
|
|
in_pIO->readBufferSize -= (offset + 1);
|
|
|
|
/* Move the rest of the buffer to the beginning of the buffer. */
|
|
memcpy( in_pIO->readBuffer,
|
|
(&in_pIO->readBuffer[offset+1]),
|
|
in_pIO->readBufferSize );
|
|
|
|
/*
|
|
* Look for the carriage return character.
|
|
* If it is there, place the null character there,
|
|
* else put the null character in the location of the linefeed character.
|
|
*/
|
|
if ( out_response[offset-1] == '\r' )
|
|
{
|
|
out_response[offset-1] = '\0';
|
|
}
|
|
else
|
|
{
|
|
out_response[offset] = '\0';
|
|
}
|
|
|
|
return NSMAIL_OK;;
|
|
}
|
|
|
|
/* Reads a line from the socket and dynamically allocates the necessary space for the response */
|
|
int IO_readDLine( IO_t * in_pIO, char** out_ppResponse )
|
|
{
|
|
int l_returnCode;
|
|
unsigned int offset = 0;
|
|
char* l_tempBuffer = NULL;
|
|
int l_bufferlength = 0;
|
|
|
|
/* Parameter validation. */
|
|
if ( in_pIO == NULL || (*out_ppResponse) != NULL )
|
|
{
|
|
return NSMAIL_ERR_INVALIDPARAM;
|
|
}
|
|
|
|
if ( in_pIO->socket < 0 )
|
|
{
|
|
return NSMAIL_ERR_NOTCONNECTED;
|
|
}
|
|
|
|
/* Make sure the IO buffer is not empty */
|
|
while( in_pIO->readBufferSize == 0 )
|
|
{
|
|
l_returnCode = UpdateBuffer( in_pIO );
|
|
if ( l_returnCode != NSMAIL_OK )
|
|
{
|
|
return l_returnCode;
|
|
}
|
|
}
|
|
|
|
/* Read byte by byte looking for the newline character. */
|
|
while(in_pIO->readBuffer[offset] != '\n')
|
|
{
|
|
offset++;
|
|
if(offset >= in_pIO->readBufferSize)
|
|
{
|
|
if(offset == in_pIO->readBufferLimit)
|
|
{
|
|
/*Grow the size of the read buffer*/
|
|
l_bufferlength = in_pIO->readBufferLimit + DEFAULT_BUFFER_LENGTH;
|
|
l_tempBuffer = in_pIO->readBuffer;
|
|
in_pIO->readBuffer = (char*)malloc(l_bufferlength*sizeof(char));
|
|
if(in_pIO->readBuffer == NULL)
|
|
{
|
|
return NSMAIL_ERR_OUTOFMEMORY;
|
|
}
|
|
memset(in_pIO->readBuffer, 0, l_bufferlength*sizeof(char));
|
|
in_pIO->readBufferLimit = l_bufferlength;
|
|
memcpy( in_pIO->readBuffer,
|
|
l_tempBuffer,
|
|
in_pIO->readBufferSize );
|
|
free(l_tempBuffer);
|
|
l_tempBuffer = NULL;
|
|
}
|
|
|
|
while(offset >= in_pIO->readBufferSize)
|
|
{
|
|
/* Put more data in the buffer. */
|
|
l_returnCode = UpdateBuffer( in_pIO );
|
|
if ( l_returnCode != NSMAIL_OK )
|
|
{
|
|
return l_returnCode;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
(*out_ppResponse) = (char*)malloc((offset + 2)*sizeof(char));
|
|
if((*out_ppResponse) == NULL)
|
|
{
|
|
return NSMAIL_ERR_OUTOFMEMORY;
|
|
}
|
|
memset((*out_ppResponse), 0, (offset + 2)*sizeof(char));
|
|
memcpy((*out_ppResponse), in_pIO->readBuffer, offset + 1);
|
|
|
|
in_pIO->readBufferSize -= (offset + 1);
|
|
|
|
/* Move the rest of the buffer to the beginning of the buffer. */
|
|
memcpy( in_pIO->readBuffer,
|
|
(&in_pIO->readBuffer[offset + 1]),
|
|
in_pIO->readBufferSize );
|
|
memset((&in_pIO->readBuffer[in_pIO->readBufferSize]), 0, in_pIO->readBufferLimit - in_pIO->readBufferSize);
|
|
|
|
return NSMAIL_OK;
|
|
}
|
|
|
|
int IO_freeDLine( char ** out_ppResponse )
|
|
{
|
|
if ( out_ppResponse == NULL || (*out_ppResponse) == NULL )
|
|
{
|
|
return NSMAIL_ERR_INVALIDPARAM;
|
|
}
|
|
|
|
free( (*out_ppResponse) );
|
|
(*out_ppResponse) = NULL;
|
|
|
|
return NSMAIL_OK;
|
|
}
|
|
|
|
/* Updates the read buffer. */
|
|
int UpdateBuffer( IO_t * in_pIO )
|
|
{
|
|
int l_nByteCount;
|
|
int l_nSelectResponse;
|
|
|
|
/* Determine if there is any data to be read in. */
|
|
l_nSelectResponse = IO_checkTimeout( in_pIO );
|
|
|
|
if ( l_nSelectResponse == 0 )
|
|
{
|
|
return NSMAIL_ERR_TIMEOUT;
|
|
}
|
|
|
|
/* Determine if there was an error. */
|
|
if ( l_nSelectResponse < 0 )
|
|
{
|
|
return NSMAIL_ERR_IO_SELECT;
|
|
}
|
|
|
|
/* Read in as much data as possible up to the max. size from the socket. */
|
|
l_nByteCount = in_pIO->ioFunctions.liof_read(
|
|
in_pIO->socket,
|
|
in_pIO->readBuffer + in_pIO->readBufferSize,
|
|
in_pIO->readBufferLimit - in_pIO->readBufferSize );
|
|
|
|
if ( l_nByteCount <= 0 )
|
|
{
|
|
return NSMAIL_ERR_IO_READ;
|
|
}
|
|
|
|
/* Set the new size of the read buffer. */
|
|
in_pIO->readBufferSize += l_nByteCount;
|
|
|
|
return NSMAIL_OK;
|
|
}
|
|
|
|
/* Set the timeout value. */
|
|
int IO_setTimeout( IO_t * in_pIO, double in_timeout )
|
|
{
|
|
if ( in_pIO == NULL )
|
|
{
|
|
return NSMAIL_ERR_INVALIDPARAM;
|
|
}
|
|
|
|
/* represents infinite blocking, not timeout */
|
|
if ( in_timeout == -1 )
|
|
{
|
|
in_pIO->timeout.tv_sec = (long)in_timeout;
|
|
return NSMAIL_OK;
|
|
}
|
|
|
|
if (in_timeout < 0.0) in_timeout = 0.0;
|
|
if (in_timeout > 1.0e8) in_timeout = 1.0e8;
|
|
|
|
in_pIO->timeout.tv_sec = (long) in_timeout;
|
|
in_pIO->timeout.tv_usec = (long) (1.0e6 * (in_timeout-(double)(long)in_timeout));
|
|
|
|
if (in_pIO->timeout.tv_usec >= 1000000)
|
|
{
|
|
in_pIO->timeout.tv_sec++;
|
|
in_pIO->timeout.tv_usec = 0;
|
|
}
|
|
|
|
return NSMAIL_OK;
|
|
}
|
|
|
|
/* Check for a timeout using select() */
|
|
int IO_checkTimeout( IO_t * in_pIO )
|
|
{
|
|
fd_set * l_fdSet;
|
|
int l_nSelectResponse;
|
|
int l_nSock = in_pIO->socket + 1;
|
|
|
|
/*
|
|
* Create the fd_set structure to be used in select().
|
|
*/
|
|
|
|
l_fdSet = (fd_set *)malloc( sizeof(fd_set) );
|
|
|
|
FD_ZERO( l_fdSet );
|
|
FD_SET( in_pIO->socket, l_fdSet );
|
|
|
|
/*
|
|
* Determine if the timeout value is infinite or not.
|
|
*/
|
|
|
|
if ( in_pIO->timeout.tv_sec == -1 )
|
|
{
|
|
l_nSelectResponse = in_pIO->ioFunctions.liof_select( l_nSock, l_fdSet, NULL, NULL, NULL );
|
|
}
|
|
else
|
|
{
|
|
l_nSelectResponse = in_pIO->ioFunctions.liof_select( l_nSock, l_fdSet, NULL, NULL, &(in_pIO->timeout) );
|
|
}
|
|
|
|
/*
|
|
* Free the fd_set structure.
|
|
*/
|
|
|
|
free( l_fdSet );
|
|
|
|
/*
|
|
* Return the result.
|
|
*/
|
|
return l_nSelectResponse;
|
|
}
|
|
|
|
|
|
/* Reset the IO functions. */
|
|
void IO_resetFunctions( IO_t * in_pIO )
|
|
{
|
|
in_pIO->ioFunctions.liof_read = NSSock_Read;
|
|
in_pIO->ioFunctions.liof_write = NSSock_Write;
|
|
in_pIO->ioFunctions.liof_socket = NSSock_Socket;
|
|
in_pIO->ioFunctions.liof_select = NSSock_Select;
|
|
in_pIO->ioFunctions.liof_connect = NSSock_Connect;
|
|
in_pIO->ioFunctions.liof_close = NSSock_Close;
|
|
}
|
|
|
|
/* Get a structure to the IO functions. */
|
|
void IO_getFunctions( IO_t * in_pIO, nsmail_io_fns_t * in_pIOFunctions )
|
|
{
|
|
in_pIOFunctions->liof_read = in_pIO->ioFunctions.liof_read;
|
|
in_pIOFunctions->liof_write = in_pIO->ioFunctions.liof_write;
|
|
in_pIOFunctions->liof_socket = in_pIO->ioFunctions.liof_socket;
|
|
in_pIOFunctions->liof_select = in_pIO->ioFunctions.liof_select;
|
|
in_pIOFunctions->liof_connect = in_pIO->ioFunctions.liof_connect;
|
|
in_pIOFunctions->liof_close = in_pIO->ioFunctions.liof_close;
|
|
}
|
|
|
|
/* Set the IO functions. */
|
|
void IO_setFunctions( IO_t * in_pIO, nsmail_io_fns_t * in_pIOFunctions )
|
|
{
|
|
in_pIO->ioFunctions.liof_read = in_pIOFunctions->liof_read;
|
|
in_pIO->ioFunctions.liof_write = in_pIOFunctions->liof_write;
|
|
in_pIO->ioFunctions.liof_socket = in_pIOFunctions->liof_socket;
|
|
in_pIO->ioFunctions.liof_select = in_pIOFunctions->liof_select;
|
|
in_pIO->ioFunctions.liof_connect = in_pIOFunctions->liof_connect;
|
|
in_pIO->ioFunctions.liof_close = in_pIOFunctions->liof_close;
|
|
}
|