xref: /AOO41X/main/sal/osl/os2/pipe.cxx (revision 87d2adbc9cadf14644c3679b041b9226f7630199)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 //#define INCL_DOSERRORS
25 #include "system.h"
26 
27 #include <osl/pipe.h>
28 #include <osl/diagnose.h>
29 #include <osl/thread.h>
30 #include <osl/mutex.h>
31 #include <osl/semaphor.h>
32 #include <osl/conditn.h>
33 #include <osl/interlck.h>
34 #include <osl/process.h>
35 #include <rtl/ustring.hxx>
36 
37 #define PIPENAMEMASK    "OSL_PIPE_%s"
38 #define SECPIPENAMEMASK "OSL_PIPE_%s_%s"
39 
40 typedef enum {
41     MSG_SYN,
42     MSG_FIN,
43     MSG_DATA,
44     MSG_UNKNOWN
45 } MessageType;
46 
47 struct oslPipeImpl {
48     oslInterlockedCount m_Reference;
49     HPIPE               hPipe;
50     HMTX                m_NamedObject;
51     APIRET              nLastError;
52     //oslSecurity       m_Security;
53     sal_Bool            m_bClosed;
54 };
55 
56 /* default size for input/output buffer */
57 static const ULONG ulBufSize = 4096;
58 
59 /* OS/2 path for pipes */
60 static const CHAR  pszPipePath[] = "\\PIPE\\";
61 static const UCHAR nPipePathLen  = sizeof (pszPipePath) - 1;
62 
63 /* global last error value to be returned from oslGetLastPipeError */
64 static APIRET ngLastError;
65 
66 using rtl::OString;
67 using rtl::OUString;
68 using rtl::OUStringToOString;
69 
70 /*****************************************************************************/
71 /* osl_create/destroy-PipeImpl */
72 /*****************************************************************************/
73 
74 static oslInterlockedCount nPipes = 0;
75 
__osl_createPipeImpl(void)76 oslPipe __osl_createPipeImpl(void)
77 {
78     oslPipe pPipe;
79 
80     pPipe = (oslPipe) calloc(1,sizeof(struct oslPipeImpl));
81 
82     pPipe->m_bClosed = sal_False;
83     pPipe->m_Reference = 1;
84     pPipe->hPipe = NULL;
85     pPipe->m_NamedObject = NULL;
86 
87     return pPipe;
88 }
89 
__osl_destroyPipeImpl(oslPipe pPipe)90 void __osl_destroyPipeImpl(oslPipe pPipe)
91 {
92     if (pPipe != NULL)
93     {
94         DosCloseMutexSem( pPipe->m_NamedObject);
95         free(pPipe);
96     }
97 }
98 
99 
100 /*****************************************************************************/
101 /* osl_createPipe  */
102 /*****************************************************************************/
osl_createPipe(rtl_uString * ustrPipeName,oslPipeOptions Options,oslSecurity Security)103 oslPipe SAL_CALL osl_createPipe(rtl_uString *ustrPipeName, oslPipeOptions Options,
104                        oslSecurity Security)
105 {
106     oslPipe pPipe;
107 
108     ULONG  ulAction;
109     CHAR   strPipeNameBuffer [CCHMAXPATHCOMP];
110     rtl_String* strPipeName=0;
111     sal_Char* pszPipeName=0;
112 
113     /* check parameters */
114     OSL_ASSERT( ustrPipeName );
115     //YD 17/04/06 OSL_ASSERT( Security == 0 );
116 
117     /* allocate impl-structure */
118     pPipe = __osl_createPipeImpl();
119     if (!pPipe)
120     {
121         OSL_TRACE( "osl_createPipe failed allocating memory.\n" );
122         return NULL;
123     }
124 
125     /* create pipe name */
126     OString sPipe = OUStringToOString(ustrPipeName, RTL_TEXTENCODING_ASCII_US);
127 #if OSL_DEBUG_LEVEL>0
128     debug_printf("osl_createPipe options 0x%x\n", Options);
129 #endif
130 
131     switch( Options )
132     {
133     case osl_Pipe_OPEN:
134         {
135             APIRET  fPipeAvailable;
136 
137             sprintf (strPipeNameBuffer, "\\PIPE\\OSL_PIPE_%s", sPipe.getStr());
138 #if OSL_DEBUG_LEVEL>0
139             debug_printf("osl_createPipe %s\n", strPipeNameBuffer);
140 #endif
141             ngLastError = DosOpen( (PCSZ)strPipeNameBuffer,
142                                 &(pPipe->hPipe), &ulAction,
143                                 0, FILE_NORMAL, FILE_OPEN,
144                                 OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYREADWRITE,
145                                 (PEAOP2) NULL);
146             // if pipe is busy, wait for it
147             if (ngLastError == ERROR_PIPE_BUSY)
148                 do
149                 {
150                     /* free instance should be available first */
151                     fPipeAvailable = DosWaitNPipe( (PCSZ)strPipeNameBuffer, -1);
152                     /* first try to open system pipe */
153                     if ( fPipeAvailable == NO_ERROR )
154                     {
155                         // We got it !
156                         ngLastError = NO_ERROR;
157                         break;
158                     }
159                     // Pipe instance maybe catched by another client -> try again
160                     printf("osl_createPipe wait for Pipe available\n");
161                 } while ( fPipeAvailable );
162         }
163         break;
164     case osl_Pipe_CREATE:
165         {
166             sprintf (strPipeNameBuffer, "\\SEM32\\OSL_SEM_%s", sPipe.getStr());
167             // check if semaphore exists (pipe create must fail for existig pipes)
168             ngLastError = DosCreateMutexSem( (PCSZ)strPipeNameBuffer, &(pPipe->m_NamedObject), 0, TRUE );
169             if (ngLastError)
170                 break;
171 
172             sprintf (strPipeNameBuffer, "\\PIPE\\OSL_PIPE_%s", sPipe.getStr());
173 #if OSL_DEBUG_LEVEL>0
174             debug_printf("osl_createPipe %s\n", strPipeNameBuffer);
175 #endif
176             ngLastError = DosCreateNPipe( (PCSZ)strPipeNameBuffer,
177                             &(pPipe->hPipe),
178                             NP_ACCESS_DUPLEX,    /* open pipe for read and write access */
179                             0xFF,                /* allow unlimited number of instances */
180                             ulBufSize,           /* output buffer size */
181                             ulBufSize,           /* input buffer size */
182                             0L                   /* use default time-out time */
183                           );
184         }
185         break;
186     default:
187         ngLastError = ERROR_INVALID_PARAMETER;
188     }
189 
190     /* if failed, release allocated memory */
191     if (ngLastError)
192     {
193         OSL_TRACE( "osl_createPipe failed %s the pipe %s, Error Code %d.\n",
194                    Options == osl_Pipe_OPEN ? "opening" : "creating",
195                    strPipeNameBuffer,
196                    ngLastError );
197         __osl_destroyPipeImpl(pPipe);
198         return NULL;
199     }
200 
201     pPipe->m_Reference= 1;
202     pPipe->m_bClosed  = sal_False;
203     //pPipe->m_Security = Security;
204     pPipe->nLastError = NO_ERROR;
205     return (oslPipe)pPipe;
206 }
207 
208 /*****************************************************************************/
209 /* osl_copyPipe  */
210 /*****************************************************************************/
osl_copyPipe(oslPipe pPipe)211 oslPipe SAL_CALL osl_copyPipe(oslPipe pPipe)
212 {
213     //oslPipe* pPipe = (oslPipe*) Pipe;
214     oslPipe pNewPipe;
215 
216 
217     /* check parameter */
218     OSL_ASSERT (pPipe);
219 
220     /* allocate impl-structure */
221     pNewPipe = __osl_createPipeImpl();
222     if (!pNewPipe) return NULL;
223 
224     /* create new handle */
225     pNewPipe->hPipe = (HPIPE) -1;
226     ngLastError  = DosDupHandle( pPipe->hPipe, &(pNewPipe->hPipe) );
227 
228     /* if failed, release allocated memory */
229     if (ngLastError)
230     {
231         OSL_TRACE( "osl_copyPipe failed duplicating pipe handle, Error-Code: %d.\n",
232                    ngLastError );
233         free (pNewPipe);
234         return NULL;
235     }
236 
237     pNewPipe->nLastError = NO_ERROR;
238     return (oslPipe)pNewPipe;
239 }
240 
osl_acquirePipe(oslPipe pPipe)241 void SAL_CALL osl_acquirePipe( oslPipe pPipe )
242 {
243     osl_incrementInterlockedCount( &(pPipe->m_Reference) );
244 }
245 
osl_releasePipe(oslPipe pPipe)246 void SAL_CALL osl_releasePipe( oslPipe pPipe )
247 {
248 //      OSL_ASSERT( pPipe );
249 
250     if( 0 == pPipe )
251         return;
252 
253     if( 0 == osl_decrementInterlockedCount( &(pPipe->m_Reference) ) )
254     {
255         if( ! pPipe->m_bClosed )
256             osl_closePipe( pPipe );
257 
258         __osl_destroyPipeImpl( pPipe );
259     }
260 }
261 
262 /*****************************************************************************/
263 /* osl_destroyPipe  */
264 /*************close****************************************************************/
osl_closePipe(oslPipe pPipe)265 void SAL_CALL osl_closePipe(oslPipe pPipe)
266 {
267     //oslPipe* pPipe = (oslPipe*) Pipe;
268     /* check parameter */
269     OSL_ASSERT (pPipe);
270 
271     if( pPipe && ! pPipe->m_bClosed )
272     {
273         pPipe->m_bClosed = sal_True;
274         /* if we have a system pipe close it */
275         if (pPipe->hPipe != 0)
276         {
277             /* disconnect client */
278             DosDisConnectNPipe (pPipe->hPipe);
279 
280             /* close the pipe */
281             DosClose (pPipe->hPipe);
282         }
283     }
284 }
285 
286 /*****************************************************************************/
287 /* osl_acceptPipe  */
288 /*****************************************************************************/
osl_acceptPipe(oslPipe pPipe)289 oslPipe SAL_CALL osl_acceptPipe(oslPipe pPipe)
290 {
291 
292 #define PINFO ((PIPEINFO *) &PipeInfoBuffer)
293 
294     ///oslPipe* pPipe = (oslPipe*) Pipe;
295     oslPipe pNewPipe;
296     BYTE     PipeInfoBuffer[sizeof(PIPEINFO) + CCHMAXPATHCOMP];
297 
298     /* check parameter */
299     OSL_ASSERT (pPipe);
300 
301     /* get pipe information */
302     pPipe->nLastError = DosQueryNPipeInfo(pPipe->hPipe,
303                                          1,
304                                          (PVOID) &PipeInfoBuffer,
305                                          sizeof(PipeInfoBuffer));
306 
307     if (pPipe->nLastError)
308     {
309         OSL_TRACE( "osl_acceptPipe failed for requesting pipe information.\n",
310                    pPipe->nLastError );
311         return NULL;
312     }
313 
314     /* create a new instance of the pipe if possible */
315     if (PINFO->cbMaxInst == -1 ||                   /* unlimited instances */
316         PINFO->cbMaxInst > PINFO->cbCurInst)
317     {
318         HPIPE hPipe;
319 
320         pNewPipe = __osl_createPipeImpl();
321 
322         if (!pNewPipe)
323         {
324             OSL_TRACE( "osl_acceptPipe failed creating new instance.\n", ngLastError );
325             free(pNewPipe);
326             return NULL;
327         }
328 
329         //pNewPipe->m_Security = pPipe->m_Security;
330 
331         pNewPipe->nLastError =
332             DosCreateNPipe( (PCSZ)PINFO->szName,
333                             &(pNewPipe->hPipe),
334                             NP_ACCESS_DUPLEX,    /* open pipe for read and write access */
335                             0xFF,                /* allow unlimited number of instances */
336                             ulBufSize,           /* output buffer size */
337                             ulBufSize,           /* input buffer size */
338                             0L                   /* use default time-out time */
339                           );
340 
341         if (pNewPipe->nLastError)
342         {
343             OSL_TRACE( "osl_acceptPipe failed creating new named pipe, Error-Code: %d.\n",
344                        pNewPipe->nLastError );
345             free(pNewPipe);
346             return NULL;
347         }
348 
349         /* switch pipe handles */
350         hPipe = pPipe->hPipe;
351         pPipe->hPipe  = pNewPipe->hPipe;
352         pNewPipe->hPipe = hPipe;
353 
354         /* connect new handle to client */
355         pNewPipe->nLastError = DosConnectNPipe( pNewPipe->hPipe );
356 
357         /* if failed, release allocated memory */
358         if (pNewPipe->nLastError)
359         {
360             OSL_TRACE( "osl_acceptPipe failed connecting pipe to client, Error-Code: %d.\n",
361                        pNewPipe->nLastError );
362 
363             osl_closePipe((oslPipe)pNewPipe);
364             return NULL;
365         }
366         return (oslPipe)pNewPipe;
367     }
368     else
369     {
370         /* connect original handle to client */
371         pPipe->nLastError = DosConnectNPipe( pPipe->hPipe );
372 
373         if (pPipe->nLastError)
374         {
375             OSL_TRACE( "osl_acceptPipe failed connecting pipe to client, Error-Code: %d.\n",
376                        pPipe->nLastError );
377             return NULL;
378         }
379 
380         return (oslPipe)pPipe;
381     }
382 }
383 
384 /*****************************************************************************/
385 /* osl_receivePipe  */
386 /*****************************************************************************/
osl_receivePipe(oslPipe pPipe,void * pBuffer,sal_Int32 BytesToRead)387 sal_Int32 SAL_CALL osl_receivePipe(oslPipe pPipe,
388                         void* pBuffer,
389                         sal_Int32 BytesToRead)
390 {
391     //oslPipe* pPipe = (oslPipe*) Pipe;
392     ULONG  ulActual;
393 
394     /* check parameter */
395     OSL_ASSERT (pPipe);
396 
397     /* read data from pipe */
398     pPipe->nLastError = DosRead( pPipe->hPipe, pBuffer, BytesToRead, &ulActual );
399 
400     /* return -1 if failed */
401     if( pPipe->nLastError )
402     {
403         OSL_TRACE( "osl_receivePipe failed receiving from Pipe, Error-Code: %d.\n",
404                    pPipe->nLastError );
405         return -1;
406     }
407 
408     return ulActual;
409 }
410 
411 
412 /*****************************************************************************/
413 /* osl_sendPipe  */
414 /*****************************************************************************/
osl_sendPipe(oslPipe pPipe,const void * pBuffer,sal_Int32 BytesToSend)415 sal_Int32 SAL_CALL osl_sendPipe(oslPipe pPipe,
416                        const void* pBuffer,
417                        sal_Int32 BytesToSend)
418 {
419     //oslPipe* pPipe = (oslPipe*) Pipe;
420     ULONG  ulActual;
421 
422     /* check parameter */
423     OSL_ASSERT (pPipe);
424 
425     /* read data from pipe */
426     pPipe->nLastError = DosWrite( pPipe->hPipe, (PVOID) pBuffer, BytesToSend, &ulActual );
427 
428     /* return -1 if failed */
429     if( pPipe->nLastError )
430     {
431         OSL_TRACE( "osl_receivePipe failed writing to Pipe, Error-Code: %d.\n",
432                    pPipe->nLastError );
433         return -1;
434     }
435 
436     return ulActual;
437 }
438 
439 
440 /*****************************************************************************/
441 /* osl_getLastPipeError  */
442 /*****************************************************************************/
443 
osl_getLastPipeError(oslPipe pPipe)444 oslPipeError SAL_CALL osl_getLastPipeError(oslPipe pPipe)
445 {
446     //oslPipe* pPipe = (oslPipe*) Pipe;
447     APIRET rc;
448 
449     /* return local error value if possible */
450     if (pPipe)
451     {
452         rc = pPipe->nLastError;
453         pPipe->nLastError = NO_ERROR;
454     } else
455         rc = ngLastError;
456 
457     /* map OS/2 error values */
458     switch (rc)
459     {
460     case NO_ERROR:                return osl_Pipe_E_None;
461     case ERROR_PATH_NOT_FOUND:    return osl_Pipe_E_NotFound;
462     case ERROR_NOT_ENOUGH_MEMORY: return osl_Pipe_E_NoBufferSpace;
463     default:                      return osl_Pipe_E_invalidError;
464     }
465 }
466 
467 /*****************************************************************************/
468 
osl_writePipe(oslPipe pPipe,const void * pBuffer,sal_Int32 n)469 sal_Int32 SAL_CALL osl_writePipe( oslPipe pPipe, const void *pBuffer , sal_Int32 n )
470 {
471     /* loop until all desired bytes were send or an error occured */
472     sal_Int32 BytesSend= 0;
473     sal_Int32 BytesToSend= n;
474 
475     OSL_ASSERT(pPipe);
476     while (BytesToSend > 0)
477     {
478         sal_Int32 RetVal;
479 
480         RetVal= osl_sendPipe(pPipe, pBuffer, BytesToSend);
481 
482         /* error occured? */
483         if(RetVal <= 0)
484         {
485             break;
486         }
487 
488         BytesToSend -= RetVal;
489         BytesSend += RetVal;
490         pBuffer= (sal_Char*)pBuffer + RetVal;
491     }
492 
493     return BytesSend;
494 }
495 
osl_readPipe(oslPipe pPipe,void * pBuffer,sal_Int32 n)496 sal_Int32 SAL_CALL osl_readPipe( oslPipe pPipe, void *pBuffer , sal_Int32 n )
497 {
498     /* loop until all desired bytes were read or an error occured */
499     sal_Int32 BytesRead= 0;
500     sal_Int32 BytesToRead= n;
501 
502     OSL_ASSERT( pPipe );
503     while (BytesToRead > 0)
504     {
505         sal_Int32 RetVal;
506         RetVal= osl_receivePipe(pPipe, pBuffer, BytesToRead);
507 
508         /* error occured? */
509         if(RetVal <= 0)
510         {
511             break;
512         }
513 
514         BytesToRead -= RetVal;
515         BytesRead += RetVal;
516         pBuffer= (sal_Char*)pBuffer + RetVal;
517     }
518     return BytesRead;
519 }
520 
521 
522 /******************************************************************************
523  *
524  *                  New io resource transfer functions
525  *
526  *****************************************************************************/
527 
528 
529 /**********************************************
530  osl_sendResourcePipe
531  *********************************************/
532 
osl_sendResourcePipe(oslPipe pPipe,oslSocket pSocket)533 sal_Bool osl_sendResourcePipe(oslPipe pPipe, oslSocket pSocket)
534 {
535     sal_Bool bRet = sal_False;
536 
537     return bRet;
538 }
539 
540 /**********************************************
541  osl_receiveResourcePipe
542  *********************************************/
543 
osl_receiveResourcePipe(oslPipe pPipe)544 oslSocket osl_receiveResourcePipe(oslPipe pPipe)
545 {
546     oslSocket pSocket=0;
547 
548     return (oslSocket) pSocket;
549 }
550 
551 
552