📄 channel.cxx
字号:
/*
* channel.cxx
*
* I/O channel classes implementation
*
* Portable Windows Library
*
* Copyright (c) 1993-1998 Equivalence Pty. Ltd.
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Portable Windows Library.
*
* The Initial Developer of the Original Code is Equivalence Pty. Ltd.
*
* Portions are Copyright (C) 1993 Free Software Foundation, Inc.
* All Rights Reserved.
*
* Contributor(s): ______________________________________.
*
* $Log: channel.cxx,v $
* Revision 1.25 1999/03/02 05:41:59 robertj
* More BeOS changes
*
* Revision 1.24 1999/02/22 13:26:53 robertj
* BeOS port changes.
*
* Revision 1.23 1998/11/30 21:51:30 robertj
* New directory structure.
*
* Revision 1.22 1998/10/16 02:03:18 robertj
* Fixed error message output to include number on unknown errors.
*
* Revision 1.21 1998/10/16 01:15:38 craigs
* Added Yield to help with cooperative multithreading.
*
* Revision 1.20 1998/10/11 02:23:16 craigs
* Fixed problem with socket writes not correctly detecting EOF
*
* Revision 1.19 1998/09/24 04:12:09 robertj
* Added open software license.
*
* Revision 1.18 1998/08/27 01:06:30 robertj
* Fixed very strange link error with GNU C library v6.
*
* Revision 1.17 1998/05/25 10:03:26 robertj
* Fixed problem with socket/channel close and blocked threads.
*
* Revision 1.16 1998/03/26 05:01:12 robertj
* Added PMutex and PSyncPoint classes.
*
* Revision 1.15 1998/01/03 22:35:04 craigs
* Added PThread support
*
* Revision 1.14 1997/02/14 09:18:36 craigs
* Changed for PProcess::Current being a reference rather that a ptr
*
* Revision 1.13 1996/11/03 04:35:32 craigs
* Added PSocket::Read to fix recv/read problem
*
* Revision 1.12 1996/09/21 05:38:28 craigs
* Added indchan pragma
*
* Revision 1.11 1996/08/03 12:04:28 craigs
* Fixed problem with PChannel::Write terminating early
* Changed for new PChannel error reporting functions
*
* Revision 1.10 1996/05/25 06:06:33 craigs
* Sun4 fixes and updated for gcc 2.7.2
*
* Revision 1.9 1996/05/03 13:11:35 craigs
* More Sun4 fixes
*
* Revision 1.8 1996/05/02 12:01:23 craigs
* More Sun4 fixes
*
* Revision 1.7 1996/04/15 10:49:11 craigs
* Last build prior to release of MibMaster v1.0
*
* Revision 1.6 1996/01/26 11:09:42 craigs
* Fixed problem with blocking accepts and incorrect socket errors
*
* Revision 1.5 1995/10/15 12:56:54 craigs
* Multiple updates - split channel implementation into multiple files
*
* Revision 1.4 1995/07/09 00:35:43 craigs
* Latest and greatest omnibus change
*
* Revision 1.3 1995/02/15 20:28:14 craigs
* Removed sleep after pipe channel open
*
// Revision 1.2 1995/01/23 22:58:01 craigs
// Changes for HPUX and Sun 4
//
*/
#pragma implementation "channel.h"
#pragma implementation "indchan.h"
#include <ptlib.h>
#include <sys/ioctl.h>
#include "../common/pchannel.cxx"
PMutex PX_iostreamMutex;
ios::ios(const ios &)
{
PAssertAlways("Cannot copy ios");
}
///////////////////////////////////////////////////////////////////////////////
//
// PChannel::PXSetIOBlock
// These functions are used to perform IO blocks.
// If the return value is FALSE, then the select call either
// returned an error or a timeout occurred. The member variable lastError
// can be used to determine which error occurred
//
BOOL PChannel::PXSetIOBlock (int type, const PTimeInterval & timeout)
{
return PXSetIOBlock(type, os_handle, timeout);
}
BOOL PChannel::PXSetIOBlock (int type, int blockHandle, const PTimeInterval & timeout)
{
if (blockHandle < 0) {
lastError = NotOpen;
return FALSE;
}
int stat = PThread::Current()->PXBlockOnIO(blockHandle, type, timeout);
// if select returned < 0, then covert errno into lastError and return FALSE
if (stat < 0)
return ConvertOSError(stat);
// if the select succeeded, then return TRUE
if (stat > 0)
return TRUE;
// otherwise, a timeout occurred so return FALSE
lastError = Timeout;
return FALSE;
}
BOOL PChannel::Read(void * buf, PINDEX len)
{
if (os_handle < 0) {
lastError = NotOpen;
return FALSE;
}
if (!PXSetIOBlock(PXReadBlock, readTimeout))
return FALSE;
if (ConvertOSError(lastReadCount = ::read(os_handle, (char *)buf, len)))
return lastReadCount > 0;
lastReadCount = 0;
return FALSE;
}
BOOL PChannel::Write(const void * buf, PINDEX len)
{
// if the os_handle isn't open, no can do
if (os_handle < 0) {
lastError = NotOpen;
return FALSE;
}
// flush the buffer before doing a write
PX_iostreamMutex.Wait();
flush();
PX_iostreamMutex.Signal();
lastWriteCount = 0;
while (len > 0) {
int sendResult = ::write(os_handle,
((char *) buf)+lastWriteCount, len); // removed const: Jurjan
if (sendResult > 0)
PThread::Yield();
else {
if (errno != EWOULDBLOCK)
return ConvertOSError(sendResult);
if (!PXSetIOBlock(PXWriteBlock, writeTimeout))
return FALSE;
sendResult = ::write(os_handle,
((char *)buf)+lastWriteCount, len); // removed const: Jurjan
}
if (!ConvertOSError(sendResult))
return FALSE;
lastWriteCount += sendResult;
len -= sendResult;
}
return TRUE;
}
BOOL PChannel::Close()
{
if (os_handle < 0) {
lastError = NotOpen;
return FALSE;
}
return ConvertOSError(PXClose());
}
BOOL PChannel::PXClose()
{
if (os_handle < 0)
return -1;
// make sure we don't have any problems
PX_iostreamMutex.Wait();
flush();
int handle = os_handle;
os_handle = -1;
PX_iostreamMutex.Signal();
#if !defined(P_PTHREADS) && !defined(BE_THREADS) && !defined(VX_TASKS) // added by Jurjan
// abort any I/O block using this os_handle
PProcess::Current().PXAbortIOBlock(handle);
#ifndef __BEOS__
DWORD cmd = 0;
::ioctl(handle, FIONBIO, &cmd);
#endif
#endif
int stat;
do {
stat = ::close(handle);
} while (stat == -1 && errno == EINTR);
return stat;
}
PString PChannel::GetErrorText(Errors, int osError = 0)
{
if (osError == 0)
return PString();
const char * err = strerror(osError);
if (err != NULL)
return err;
return psprintf("Unknown error %d", osError);
}
PString PChannel::GetErrorText() const
{
return GetErrorText(lastError, osError);
}
BOOL PChannel::ConvertOSError(int err)
{
return ConvertOSError(err, lastError, osError);
}
BOOL PChannel::ConvertOSError(int err, Errors & lastError, int & osError)
{
osError = (err >= 0) ? 0 : errno;
switch (osError) {
case 0 :
lastError = NoError;
return TRUE;
case EMSGSIZE:
lastError = BufferTooSmall;
break;
case EINTR:
lastError = Interrupted;
break;
case EEXIST:
lastError = FileExists;
break;
case EISDIR:
case EROFS:
case EACCES:
case EPERM:
lastError = AccessDenied;
break;
#ifndef __BEOS__
case ETXTBSY:
lastError = DeviceInUse;
break;
#endif
case EFAULT:
case ELOOP:
case EBADF:
case EINVAL:
lastError = BadParameter;
break;
case ENOENT :
case ENAMETOOLONG:
case ENOTDIR:
lastError = NotFound;
break;
case EMFILE:
case ENFILE:
case ENOMEM :
lastError = NoMemory;
break;
case ENOSPC:
lastError = DiskFull;
break;
default :
lastError = Miscellaneous;
break;
}
return FALSE;
}
///////////////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -