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
__osl_createPipeImpl(void)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
__osl_destroyPipeImpl(oslPipe pPipe)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 /*****************************************************************************/
osl_createPipe(rtl_uString * ustrPipeName,oslPipeOptions Options,oslSecurity Security)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 /*****************************************************************************/
osl_copyPipe(oslPipe pPipe)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
osl_acquirePipe(oslPipe pPipe)239 void SAL_CALL osl_acquirePipe( oslPipe pPipe )
240 {
241 osl_incrementInterlockedCount( &(pPipe->m_Reference) );
242 }
243
osl_releasePipe(oslPipe pPipe)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****************************************************************/
osl_closePipe(oslPipe pPipe)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 /*****************************************************************************/
osl_acceptPipe(oslPipe pPipe)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 /*****************************************************************************/
osl_receivePipe(oslPipe pPipe,void * pBuffer,sal_Int32 BytesToRead)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 /*****************************************************************************/
osl_sendPipe(oslPipe pPipe,const void * pBuffer,sal_Int32 BytesToSend)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
osl_getLastPipeError(oslPipe pPipe)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
osl_writePipe(oslPipe pPipe,const void * pBuffer,sal_Int32 n)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
osl_readPipe(oslPipe pPipe,void * pBuffer,sal_Int32 n)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
osl_sendResourcePipe(oslPipe pPipe,oslSocket pSocket)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
osl_receiveResourcePipe(oslPipe pPipe)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