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 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 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 /*****************************************************************************/ 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 /*****************************************************************************/ 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 239 void SAL_CALL osl_acquirePipe( oslPipe pPipe ) 240 { 241 osl_incrementInterlockedCount( &(pPipe->m_Reference) ); 242 } 243 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****************************************************************/ 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 /*****************************************************************************/ 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 /*****************************************************************************/ 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 /*****************************************************************************/ 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 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 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 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 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 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