blob: 32ffe13b060b576ced223beed44df2fce1064e16 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
//#define INCL_DOSERRORS
#include "system.h"
#include <osl/pipe.h>
#include <osl/diagnose.h>
#include <osl/thread.h>
#include <osl/mutex.h>
#include <osl/semaphor.h>
#include <osl/conditn.h>
#include <osl/interlck.h>
#include <osl/process.h>
#include <rtl/ustring.hxx>
#define PIPENAMEMASK "OSL_PIPE_%s"
#define SECPIPENAMEMASK "OSL_PIPE_%s_%s"
typedef enum {
MSG_SYN,
MSG_FIN,
MSG_DATA,
MSG_UNKNOWN
} MessageType;
struct oslPipeImpl {
oslInterlockedCount m_Reference;
HPIPE hPipe;
HMTX m_NamedObject;
APIRET nLastError;
//oslSecurity m_Security;
sal_Bool m_bClosed;
};
/* default size for input/output buffer */
static const ULONG ulBufSize = 4096;
/* OS/2 path for pipes */
static const CHAR pszPipePath[] = "\\PIPE\\";
static const UCHAR nPipePathLen = sizeof (pszPipePath) - 1;
/* global last error value to be returned from oslGetLastPipeError */
static APIRET ngLastError;
using rtl::OString;
using rtl::OUString;
using rtl::OUStringToOString;
/*****************************************************************************/
/* osl_create/destroy-PipeImpl */
/*****************************************************************************/
static oslInterlockedCount nPipes = 0;
oslPipe __osl_createPipeImpl(void)
{
oslPipe pPipe;
pPipe = (oslPipe) calloc(1,sizeof(struct oslPipeImpl));
pPipe->m_bClosed = sal_False;
pPipe->m_Reference = 1;
pPipe->hPipe = NULL;
pPipe->m_NamedObject = NULL;
return pPipe;
}
void __osl_destroyPipeImpl(oslPipe pPipe)
{
if (pPipe != NULL)
{
DosCloseMutexSem( pPipe->m_NamedObject);
free(pPipe);
}
}
/*****************************************************************************/
/* osl_createPipe */
/*****************************************************************************/
oslPipe SAL_CALL osl_createPipe(rtl_uString *ustrPipeName, oslPipeOptions Options,
oslSecurity Security)
{
oslPipe pPipe;
ULONG ulAction;
CHAR strPipeNameBuffer [CCHMAXPATHCOMP];
rtl_String* strPipeName=0;
sal_Char* pszPipeName=0;
/* check parameters */
OSL_ASSERT( ustrPipeName );
//YD 17/04/06 OSL_ASSERT( Security == 0 );
/* allocate impl-structure */
pPipe = __osl_createPipeImpl();
if (!pPipe)
{
OSL_TRACE( "osl_createPipe failed allocating memory.\n" );
return NULL;
}
/* create pipe name */
OString sPipe = OUStringToOString(ustrPipeName, RTL_TEXTENCODING_ASCII_US);
#if OSL_DEBUG_LEVEL>0
debug_printf("osl_createPipe options 0x%x\n", Options);
#endif
switch( Options )
{
case osl_Pipe_OPEN:
{
APIRET fPipeAvailable;
sprintf (strPipeNameBuffer, "\\PIPE\\OSL_PIPE_%s", sPipe.getStr());
#if OSL_DEBUG_LEVEL>0
debug_printf("osl_createPipe %s\n", strPipeNameBuffer);
#endif
ngLastError = DosOpen( (PCSZ)strPipeNameBuffer,
&(pPipe->hPipe), &ulAction,
0, FILE_NORMAL, FILE_OPEN,
OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYREADWRITE,
(PEAOP2) NULL);
// if pipe is busy, wait for it
if (ngLastError == ERROR_PIPE_BUSY)
do
{
/* free instance should be available first */
fPipeAvailable = DosWaitNPipe( (PCSZ)strPipeNameBuffer, -1);
/* first try to open system pipe */
if ( fPipeAvailable == NO_ERROR )
{
// We got it !
ngLastError = NO_ERROR;
break;
}
// Pipe instance maybe catched by another client -> try again
printf("osl_createPipe wait for Pipe available\n");
} while ( fPipeAvailable );
}
break;
case osl_Pipe_CREATE:
{
sprintf (strPipeNameBuffer, "\\SEM32\\OSL_SEM_%s", sPipe.getStr());
// check if semaphore exists (pipe create must fail for existig pipes)
ngLastError = DosCreateMutexSem( (PCSZ)strPipeNameBuffer, &(pPipe->m_NamedObject), 0, TRUE );
if (ngLastError)
break;
sprintf (strPipeNameBuffer, "\\PIPE\\OSL_PIPE_%s", sPipe.getStr());
#if OSL_DEBUG_LEVEL>0
debug_printf("osl_createPipe %s\n", strPipeNameBuffer);
#endif
ngLastError = DosCreateNPipe( (PCSZ)strPipeNameBuffer,
&(pPipe->hPipe),
NP_ACCESS_DUPLEX, /* open pipe for read and write access */
0xFF, /* allow unlimited number of instances */
ulBufSize, /* output buffer size */
ulBufSize, /* input buffer size */
0L /* use default time-out time */
);
}
break;
default:
ngLastError = ERROR_INVALID_PARAMETER;
}
/* if failed, release allocated memory */
if (ngLastError)
{
OSL_TRACE( "osl_createPipe failed %s the pipe %s, Error Code %d.\n",
Options == osl_Pipe_OPEN ? "opening" : "creating",
strPipeNameBuffer,
ngLastError );
__osl_destroyPipeImpl(pPipe);
return NULL;
}
pPipe->m_Reference= 1;
pPipe->m_bClosed = sal_False;
//pPipe->m_Security = Security;
pPipe->nLastError = NO_ERROR;
return (oslPipe)pPipe;
}
/*****************************************************************************/
/* osl_copyPipe */
/*****************************************************************************/
oslPipe SAL_CALL osl_copyPipe(oslPipe pPipe)
{
//oslPipe* pPipe = (oslPipe*) Pipe;
oslPipe pNewPipe;
/* check parameter */
OSL_ASSERT (pPipe);
/* allocate impl-structure */
pNewPipe = __osl_createPipeImpl();
if (!pNewPipe) return NULL;
/* create new handle */
pNewPipe->hPipe = (HPIPE) -1;
ngLastError = DosDupHandle( pPipe->hPipe, &(pNewPipe->hPipe) );
/* if failed, release allocated memory */
if (ngLastError)
{
OSL_TRACE( "osl_copyPipe failed duplicating pipe handle, Error-Code: %d.\n",
ngLastError );
free (pNewPipe);
return NULL;
}
pNewPipe->nLastError = NO_ERROR;
return (oslPipe)pNewPipe;
}
void SAL_CALL osl_acquirePipe( oslPipe pPipe )
{
osl_incrementInterlockedCount( &(pPipe->m_Reference) );
}
void SAL_CALL osl_releasePipe( oslPipe pPipe )
{
// OSL_ASSERT( pPipe );
if( 0 == pPipe )
return;
if( 0 == osl_decrementInterlockedCount( &(pPipe->m_Reference) ) )
{
if( ! pPipe->m_bClosed )
osl_closePipe( pPipe );
__osl_destroyPipeImpl( pPipe );
}
}
/*****************************************************************************/
/* osl_destroyPipe */
/*************close****************************************************************/
void SAL_CALL osl_closePipe(oslPipe pPipe)
{
//oslPipe* pPipe = (oslPipe*) Pipe;
/* check parameter */
OSL_ASSERT (pPipe);
if( pPipe && ! pPipe->m_bClosed )
{
pPipe->m_bClosed = sal_True;
/* if we have a system pipe close it */
if (pPipe->hPipe != 0)
{
/* disconnect client */
DosDisConnectNPipe (pPipe->hPipe);
/* close the pipe */
DosClose (pPipe->hPipe);
}
}
}
/*****************************************************************************/
/* osl_acceptPipe */
/*****************************************************************************/
oslPipe SAL_CALL osl_acceptPipe(oslPipe pPipe)
{
#define PINFO ((PIPEINFO *) &PipeInfoBuffer)
///oslPipe* pPipe = (oslPipe*) Pipe;
oslPipe pNewPipe;
BYTE PipeInfoBuffer[sizeof(PIPEINFO) + CCHMAXPATHCOMP];
/* check parameter */
OSL_ASSERT (pPipe);
/* get pipe information */
pPipe->nLastError = DosQueryNPipeInfo(pPipe->hPipe,
1,
(PVOID) &PipeInfoBuffer,
sizeof(PipeInfoBuffer));
if (pPipe->nLastError)
{
OSL_TRACE( "osl_acceptPipe failed for requesting pipe information.\n",
pPipe->nLastError );
return NULL;
}
/* create a new instance of the pipe if possible */
if (PINFO->cbMaxInst == -1 || /* unlimited instances */
PINFO->cbMaxInst > PINFO->cbCurInst)
{
HPIPE hPipe;
pNewPipe = __osl_createPipeImpl();
if (!pNewPipe)
{
OSL_TRACE( "osl_acceptPipe failed creating new instance.\n", ngLastError );
free(pNewPipe);
return NULL;
}
//pNewPipe->m_Security = pPipe->m_Security;
pNewPipe->nLastError =
DosCreateNPipe( (PCSZ)PINFO->szName,
&(pNewPipe->hPipe),
NP_ACCESS_DUPLEX, /* open pipe for read and write access */
0xFF, /* allow unlimited number of instances */
ulBufSize, /* output buffer size */
ulBufSize, /* input buffer size */
0L /* use default time-out time */
);
if (pNewPipe->nLastError)
{
OSL_TRACE( "osl_acceptPipe failed creating new named pipe, Error-Code: %d.\n",
pNewPipe->nLastError );
free(pNewPipe);
return NULL;
}
/* switch pipe handles */
hPipe = pPipe->hPipe;
pPipe->hPipe = pNewPipe->hPipe;
pNewPipe->hPipe = hPipe;
/* connect new handle to client */
pNewPipe->nLastError = DosConnectNPipe( pNewPipe->hPipe );
/* if failed, release allocated memory */
if (pNewPipe->nLastError)
{
OSL_TRACE( "osl_acceptPipe failed connecting pipe to client, Error-Code: %d.\n",
pNewPipe->nLastError );
osl_closePipe((oslPipe)pNewPipe);
return NULL;
}
return (oslPipe)pNewPipe;
}
else
{
/* connect original handle to client */
pPipe->nLastError = DosConnectNPipe( pPipe->hPipe );
if (pPipe->nLastError)
{
OSL_TRACE( "osl_acceptPipe failed connecting pipe to client, Error-Code: %d.\n",
pPipe->nLastError );
return NULL;
}
return (oslPipe)pPipe;
}
}
/*****************************************************************************/
/* osl_receivePipe */
/*****************************************************************************/
sal_Int32 SAL_CALL osl_receivePipe(oslPipe pPipe,
void* pBuffer,
sal_Int32 BytesToRead)
{
//oslPipe* pPipe = (oslPipe*) Pipe;
ULONG ulActual;
/* check parameter */
OSL_ASSERT (pPipe);
/* read data from pipe */
pPipe->nLastError = DosRead( pPipe->hPipe, pBuffer, BytesToRead, &ulActual );
/* return -1 if failed */
if( pPipe->nLastError )
{
OSL_TRACE( "osl_receivePipe failed receiving from Pipe, Error-Code: %d.\n",
pPipe->nLastError );
return -1;
}
return ulActual;
}
/*****************************************************************************/
/* osl_sendPipe */
/*****************************************************************************/
sal_Int32 SAL_CALL osl_sendPipe(oslPipe pPipe,
const void* pBuffer,
sal_Int32 BytesToSend)
{
//oslPipe* pPipe = (oslPipe*) Pipe;
ULONG ulActual;
/* check parameter */
OSL_ASSERT (pPipe);
/* read data from pipe */
pPipe->nLastError = DosWrite( pPipe->hPipe, (PVOID) pBuffer, BytesToSend, &ulActual );
/* return -1 if failed */
if( pPipe->nLastError )
{
OSL_TRACE( "osl_receivePipe failed writing to Pipe, Error-Code: %d.\n",
pPipe->nLastError );
return -1;
}
return ulActual;
}
/*****************************************************************************/
/* osl_getLastPipeError */
/*****************************************************************************/
oslPipeError SAL_CALL osl_getLastPipeError(oslPipe pPipe)
{
//oslPipe* pPipe = (oslPipe*) Pipe;
APIRET rc;
/* return local error value if possible */
if (pPipe)
{
rc = pPipe->nLastError;
pPipe->nLastError = NO_ERROR;
} else
rc = ngLastError;
/* map OS/2 error values */
switch (rc)
{
case NO_ERROR: return osl_Pipe_E_None;
case ERROR_PATH_NOT_FOUND: return osl_Pipe_E_NotFound;
case ERROR_NOT_ENOUGH_MEMORY: return osl_Pipe_E_NoBufferSpace;
default: return osl_Pipe_E_invalidError;
}
}
/*****************************************************************************/
sal_Int32 SAL_CALL osl_writePipe( oslPipe pPipe, const void *pBuffer , sal_Int32 n )
{
/* loop until all desired bytes were send or an error occured */
sal_Int32 BytesSend= 0;
sal_Int32 BytesToSend= n;
OSL_ASSERT(pPipe);
while (BytesToSend > 0)
{
sal_Int32 RetVal;
RetVal= osl_sendPipe(pPipe, pBuffer, BytesToSend);
/* error occured? */
if(RetVal <= 0)
{
break;
}
BytesToSend -= RetVal;
BytesSend += RetVal;
pBuffer= (sal_Char*)pBuffer + RetVal;
}
return BytesSend;
}
sal_Int32 SAL_CALL osl_readPipe( oslPipe pPipe, void *pBuffer , sal_Int32 n )
{
/* loop until all desired bytes were read or an error occured */
sal_Int32 BytesRead= 0;
sal_Int32 BytesToRead= n;
OSL_ASSERT( pPipe );
while (BytesToRead > 0)
{
sal_Int32 RetVal;
RetVal= osl_receivePipe(pPipe, pBuffer, BytesToRead);
/* error occured? */
if(RetVal <= 0)
{
break;
}
BytesToRead -= RetVal;
BytesRead += RetVal;
pBuffer= (sal_Char*)pBuffer + RetVal;
}
return BytesRead;
}
/******************************************************************************
*
* New io resource transfer functions
*
*****************************************************************************/
/**********************************************
osl_sendResourcePipe
*********************************************/
sal_Bool osl_sendResourcePipe(oslPipe pPipe, oslSocket pSocket)
{
sal_Bool bRet = sal_False;
return bRet;
}
/**********************************************
osl_receiveResourcePipe
*********************************************/
oslSocket osl_receiveResourcePipe(oslPipe pPipe)
{
oslSocket pSocket=0;
return (oslSocket) pSocket;
}