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