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