xref: /trunk/main/sal/osl/os2/pipe.cxx (revision 86e1cf34)
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 occurred */
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 occurred? */
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 occurred */
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 occurred? */
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