| /************************************************************** |
| * |
| * 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; |
| } |
| |
| |