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 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 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 /*****************************************************************************/ 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 /*****************************************************************************/ 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 241 void SAL_CALL osl_acquirePipe( oslPipe pPipe ) 242 { 243 osl_incrementInterlockedCount( &(pPipe->m_Reference) ); 244 } 245 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****************************************************************/ 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 /*****************************************************************************/ 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 /*****************************************************************************/ 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 /*****************************************************************************/ 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 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 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 occured */ 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 occured? */ 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 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 occured */ 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 occured? */ 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 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 544 oslSocket osl_receiveResourcePipe(oslPipe pPipe) 545 { 546 oslSocket pSocket=0; 547 548 return (oslSocket) pSocket; 549 } 550 551 552