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