Пример #1
0
int IOCPNetwork::recv(iocp_key_t key, byte* buf, size_t len, size_t timeout, iocp_proc_t func, void* param)
{
	if( !_inited ) return IOCP_UNINITIALIZED;
	iocp_context_t* context = reinterpret_cast<iocp_context_t*>(key);

	/*
	* 执行WSARecv
	*/
	int ret = IOCP_PENDING;

	if(context->lockPtr) context->lockPtr->rlock();
	if(context->status != IOCP_NORMAL)
	{
		/* 允许一个接收操作和一个发送操作同时进行 */
		ret = context->status; 
	}
	else if(sessionTimeout(context))
	{
		ret = IOCP_SESSIONTIMEO;
	}
	else
	{
		assert(context->readOlp.oppType == IOCP_NONE);
		context->readOlp.oppType = IOCP_RECV;
		context->readOlp.buf = buf;
		context->readOlp.len = len;
		context->readOlp.timeout = timeout;
		assert(context->readOlp.timer == NULL);
		context->readOlp.iocpProc = func;
		context->readOlp.param = param;
		context->readOlp.realLen = len;

		/*
		* 检查是否超出速度限制,如果是,则延时发送/接收
		*/
		size_t delay = 0;
		if(context->readOlp.speedLmt > 0 && context->readOlp.lastCompleteCounter != 0)
		{
			/* 
			* 按照最大速度限制,发送 nSended数据完成应该在 nExpectTime 这个时间点完成.
			*/
			__int64 expectTime = _hrt.getCounters(static_cast<__int64>(context->readOlp.transfered * 1.0 / context->readOlp.speedLmt * 1000));
			expectTime += context->startCounter;

			if(expectTime > context->readOlp.lastCompleteCounter) /* 完成的时间点提前,说明速度超标 */
			{
				/* 计算出定时器触发的时间. */
				delay = static_cast<size_t>(_hrt.getMs(expectTime - context->readOlp.lastCompleteCounter));
				if(delay > IOCP_MAXWAITTIME_ONSPEEDLMT)
				{
					/* 超过最长等待时间,下一次发送一个最小包. */
					delay = IOCP_MAXWAITTIME_ONSPEEDLMT;
					if(context->readOlp.len > IOCP_MINBUFLEN_ONSPEEDLMT)
					{
						context->readOlp.realLen = IOCP_MINBUFLEN_ONSPEEDLMT;
					}
				}
				else
				{
					/* 下一次可以接收一个最大包. */
					context->readOlp.realLen = context->readOlp.len;
				}
			}
		}


		/*
		* 直接发送或者设置一个定时器延时发送
		*/
		if(delay > 0)
		{
			/*
			*  设置一个延时操作的定时器,并返回成功. 真正操作的结果等定时器到期后再通过回调函数通知.
			*/
			context->readOlp.oppType = IOCP_DELAY_READ;
			context->readOlp.timer = _timerQueue.createTimer(delay, delayRecvProc, context);
		}
		else
		{
			/*
			* 设置超时定时器,然后接收
			*/
			if(context->readOlp.timeout > 0)
			{
				context->readOlp.timer = _timerQueue.createTimer(context->readOlp.timeout, readTimeoutProc, context);
			}

			ret = realRecv(context);

			/*
			* 如果接收操作失败,应该恢复现场,以便下一次调用可以成功.
			*/
			if(IOCP_PENDING != ret)
			{
				cleanOlp(&context->readOlp);
			}
		}
	}
	if(context->lockPtr) context->lockPtr->unlock();
	
	return ret;
}
Пример #2
0
int IOCPNetwork::accept(iocp_key_t key, SOCKET sockNew, byte* buf, size_t len, size_t timeout, iocp_proc_t func, void* param)
{
	if( !_inited ) return IOCP_UNINITIALIZED;
	if(len < (sizeof(sockaddr_in) + 16) * 2) return IOCP_BUFFERROR; /* 缓冲区长度不够 */
	iocp_context_t* context = reinterpret_cast<iocp_context_t*>(key);
	assert(IOCP_HANDLE_SOCKET == context->type);

	/*
	* 获得AcceptEx()函数指针并调用之,参考MSDN关于AcceptEx的示例代码.
	*/
	SOCKET sockListen = reinterpret_cast<SOCKET>(context->h);
	DWORD dwBytesReceived = 0;
	GUID GuidAcceptEx = WSAID_ACCEPTEX;
	LPFN_ACCEPTEX lpfnAcceptEx = NULL;
	DWORD dwBytes = 0;
	if( 0 != WSAIoctl(sockListen, SIO_GET_EXTENSION_FUNCTION_POINTER, &GuidAcceptEx, sizeof(GuidAcceptEx), &lpfnAcceptEx, sizeof(lpfnAcceptEx), &dwBytes, NULL, NULL) )
	{
		assert(0);
		_lastErrorCode = WSAGetLastError();
		return IOCP_UNDEFINED;
	}

	/*
	* 设置标记,然后调用AcceptEx,加锁以确保同步正确
	* 由于发送和接收分别对应不同的重叠结构,所以可以用读写锁同时进行,只要套接字状态正常.
	*/
	int ret = IOCP_PENDING;
	if(context->lockPtr) context->lockPtr->rlock();
	if(context->status != IOCP_NORMAL)
	{
		ret = context->status; 
	}
	else if(sessionTimeout(context))
	{
		ret = IOCP_SESSIONTIMEO;
	}
	else
	{
		/* assert检查:不要同时投递多个同类型的操作,由程序逻辑确保这一点,而不用同步量以提高并发量,否则只能用互斥锁了. */
		assert(context->readOlp.oppType == IOCP_NONE);
		context->readOlp.oppType = IOCP_ACCEPT;
		context->readOlp.buf = buf;
		context->readOlp.len = len;
		context->readOlp.realLen = len;
		context->readOlp.iocpProc = func;
		context->readOlp.param = param;
		context->readOlp.timeout = timeout;
		if(timeout > 0)
		{
			/* 先创建定时器,acceptEx失败再删除是有必要的,尤其是在没有同步的情况下 */
			context->readOlp.timer = _timerQueue.createTimer(timeout, readTimeoutProc, context);
		}

		if( !lpfnAcceptEx(sockListen, sockNew, buf, 
			len - (sizeof(sockaddr_in) + 16) * 2 , sizeof(sockaddr_in) + 16, sizeof(sockaddr_in) + 16, 
			&dwBytesReceived, reinterpret_cast<LPOVERLAPPED>(&context->readOlp)) )
		{
			if( WSA_IO_PENDING != WSAGetLastError())
			{
				assert(0);
				_lastErrorCode = WSAGetLastError();
				ret = IOCP_UNDEFINED;
			}
		}
		else
		{
			assert(0);
			ret = IOCP_UNDEFINED;
		}

		/*
		* 调用失败,清除标志回收资源
		*/
		if(ret != IOCP_PENDING)
		{
			cleanOlp(&context->readOlp);
		}
	}

	if(context->lockPtr) context->lockPtr->unlock();

	return ret;
}
Пример #3
0
int IOCPNetwork::connect(iocp_key_t key, sockaddr* addr, byte* buf, size_t len, size_t timeout, iocp_proc_t func, void* param)
{
	if( !_inited ) return IOCP_UNINITIALIZED;
	iocp_context_t* context = reinterpret_cast<iocp_context_t*>(key);
	assert(IOCP_HANDLE_SOCKET == context->type);

	/*
	* 取得ConnectEx函数指针
	*/
	SOCKET s = reinterpret_cast<SOCKET>(context->h);
	DWORD dwBytesReceived = 0;
	GUID GuidConnectEx = WSAID_CONNECTEX;
	LPFN_CONNECTEX lpfnConnectEx = NULL;
	DWORD dwBytes = 0;
	if( 0 != WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &GuidConnectEx, sizeof(GuidConnectEx), &lpfnConnectEx, sizeof(lpfnConnectEx), &dwBytes, NULL, NULL) )
	{
		assert(0);
		_lastErrorCode = WSAGetLastError();
		return IOCP_UNDEFINED;
	}

	/*
	* 执行ConnectEx
	*/

	int ret = IOCP_PENDING;
	DWORD bytesSent = 0;
	if(context->lockPtr) context->lockPtr->rlock();
	if(context->status != IOCP_NORMAL)
	{
		ret = context->status; 
	}
	else if(sessionTimeout(context))
	{
		ret = IOCP_SESSIONTIMEO;
	}
	else
	{
		assert(context->writeOlp.oppType == IOCP_NONE);
		context->writeOlp.oppType = IOCP_CONNECT;
		context->writeOlp.buf = buf;
		context->writeOlp.len = len;
		context->writeOlp.iocpProc = func;
		context->writeOlp.param = param;
		context->writeOlp.realLen = len;
		context->writeOlp.timeout = timeout;

		if(timeout > 0)
		{
			context->writeOlp.timer = _timerQueue.createTimer(timeout, writeTimeoutProc, context);
		}

		if( !lpfnConnectEx(s, addr, sizeof(sockaddr), buf, len, &bytesSent, reinterpret_cast<LPOVERLAPPED>(&context->writeOlp)) )
		{
			int errorCode = WSAGetLastError();
			if( WSA_IO_PENDING != errorCode )
			{
				assert(0);
				_lastErrorCode = errorCode;
				ret = IOCP_UNDEFINED;
			}
		}
		else
		{
			assert(0);
			ret = IOCP_UNDEFINED;
		}

		/*
		* 调用失败,清除标志回收资源
		*/
		if(ret != IOCP_PENDING)
		{
			cleanOlp(&context->writeOlp);
		}
	}
	if(context->lockPtr) context->lockPtr->unlock();

	return ret;
}
Пример #4
0
int IOCPNetwork::send(iocp_key_t key, const byte* buf, size_t len, size_t timeout, iocp_proc_t func, void* param)
{
	if( !_inited ) return IOCP_UNINITIALIZED;
	iocp_context_t* context = reinterpret_cast<iocp_context_t*>(key);

	/*
	* 执行WSARecv
	*/
	int ret = IOCP_PENDING;

	if(context->lockPtr) context->lockPtr->rlock();
	if(context->status != IOCP_NORMAL)
	{
		/* 允许一个接收操作和一个发送操作同时进行 */
		ret = context->status; 
	}
	else if(sessionTimeout(context))
	{
		ret = IOCP_SESSIONTIMEO;
	}
	else
	{
		assert(context->writeOlp.oppType == IOCP_NONE);
		context->writeOlp.oppType = IOCP_SEND;
		context->writeOlp.buf = const_cast<byte*>(buf);
		context->writeOlp.len = len;
		context->writeOlp.timeout = timeout;
		assert(context->writeOlp.timer == NULL);
		context->writeOlp.iocpProc = func;
		context->writeOlp.param = param;
		context->writeOlp.realLen = len;

		/*
		* 检查是否超出速度限制,如果是,则延时发送/接收
		* 第一次操作不检查
		*/
		size_t delay = 0;
		if(context->writeOlp.speedLmt > 0 && context->writeOlp.lastCompleteCounter != 0)
		{
			/* 
			* 按照最大速度限制,发送 nSended数据完成应该在 nExpectTime 这个时间点完成.
			*/
			__int64 expectTime = _hrt.getCounters(static_cast<__int64>(context->writeOlp.transfered * 1.0 / context->writeOlp.speedLmt * 1000));
			expectTime += context->startCounter;

			if(expectTime > context->writeOlp.lastCompleteCounter) /* 完成的时间点提前,说明速度超标 */
			{
				/* 计算出定时器触发的时间. */
				delay = static_cast<size_t>(_hrt.getMs(expectTime - context->writeOlp.lastCompleteCounter));
				if(delay > IOCP_MAXWAITTIME_ONSPEEDLMT)
				{
					/* 超过最长等待时间,下一次发送一个最小包. */
					delay = IOCP_MAXWAITTIME_ONSPEEDLMT;
					if(context->writeOlp.len > IOCP_MINBUFLEN_ONSPEEDLMT)
					{
						context->writeOlp.realLen = IOCP_MINBUFLEN_ONSPEEDLMT;
					}
				}
				else
				{
					/* 下一次可以发送一个最大包. */
					context->writeOlp.realLen = context->writeOlp.len;
				}

				//TRACE(_T("delay send:%dms.\r\n"), delay);
			}
		}

		/*
		* 直接发送或者设置一个定时器延时发送
		*/
		if(delay > 0)
		{
			context->writeOlp.oppType = IOCP_DELAY_WRITE;
			context->writeOlp.timer = _timerQueue.createTimer(delay, delaySendProc, context);
		}
		else
		{
			/*
			* 设置超时定时器,然后发送
			*/
			if(context->writeOlp.timeout > 0)
			{
				context->writeOlp.timer = _timerQueue.createTimer(context->writeOlp.timeout, readTimeoutProc, context);
			}

			ret = realSend(context);

			if( ret != IOCP_PENDING)
			{
				cleanOlp(&context->writeOlp);
			}
		}
	}
	if(context->lockPtr) context->lockPtr->unlock();
	
	return ret;
}
Пример #5
0
int ONVIF::AudioEncoderConfiguration::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
    _id = QObject::qt_metacall(_c, _id, _a);
    if (_id < 0)
        return _id;
    if (_c == QMetaObject::InvokeMetaMethod) {
        if (_id < 13)
            qt_static_metacall(this, _c, _id, _a);
        _id -= 13;
    } else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
        if (_id < 13)
            *reinterpret_cast<int*>(_a[0]) = -1;
        _id -= 13;
    }
#ifndef QT_NO_PROPERTIES
      else if (_c == QMetaObject::ReadProperty) {
        void *_v = _a[0];
        switch (_id) {
        case 0: *reinterpret_cast< QString*>(_v) = token(); break;
        case 1: *reinterpret_cast< QString*>(_v) = name(); break;
        case 2: *reinterpret_cast< int*>(_v) = useCount(); break;
        case 3: *reinterpret_cast< QString*>(_v) = encoding(); break;
        case 4: *reinterpret_cast< int*>(_v) = bitrate(); break;
        case 5: *reinterpret_cast< int*>(_v) = sampleRate(); break;
        case 6: *reinterpret_cast< QString*>(_v) = type(); break;
        case 7: *reinterpret_cast< QString*>(_v) = ipv4Address(); break;
        case 8: *reinterpret_cast< QString*>(_v) = ipv6Address(); break;
        case 9: *reinterpret_cast< int*>(_v) = port(); break;
        case 10: *reinterpret_cast< int*>(_v) = ttl(); break;
        case 11: *reinterpret_cast< bool*>(_v) = autoStart(); break;
        case 12: *reinterpret_cast< QString*>(_v) = sessionTimeout(); break;
        }
        _id -= 13;
    } else if (_c == QMetaObject::WriteProperty) {
        void *_v = _a[0];
        switch (_id) {
        case 0: setToken(*reinterpret_cast< QString*>(_v)); break;
        case 1: setName(*reinterpret_cast< QString*>(_v)); break;
        case 2: setUseCount(*reinterpret_cast< int*>(_v)); break;
        case 3: setEncoding(*reinterpret_cast< QString*>(_v)); break;
        case 4: setBitrate(*reinterpret_cast< int*>(_v)); break;
        case 5: setSampleRate(*reinterpret_cast< int*>(_v)); break;
        case 6: setType(*reinterpret_cast< QString*>(_v)); break;
        case 7: setIpv4Address(*reinterpret_cast< QString*>(_v)); break;
        case 8: setIpv6Address(*reinterpret_cast< QString*>(_v)); break;
        case 9: setPort(*reinterpret_cast< int*>(_v)); break;
        case 10: setTtl(*reinterpret_cast< int*>(_v)); break;
        case 11: setAutoStart(*reinterpret_cast< bool*>(_v)); break;
        case 12: setSessionTimeout(*reinterpret_cast< QString*>(_v)); break;
        }
        _id -= 13;
    } else if (_c == QMetaObject::ResetProperty) {
        _id -= 13;
    } else if (_c == QMetaObject::QueryPropertyDesignable) {
        _id -= 13;
    } else if (_c == QMetaObject::QueryPropertyScriptable) {
        _id -= 13;
    } else if (_c == QMetaObject::QueryPropertyStored) {
        _id -= 13;
    } else if (_c == QMetaObject::QueryPropertyEditable) {
        _id -= 13;
    } else if (_c == QMetaObject::QueryPropertyUser) {
        _id -= 13;
    } else if (_c == QMetaObject::RegisterPropertyMetaType) {
        if (_id < 13)
            *reinterpret_cast<int*>(_a[0]) = -1;
        _id -= 13;
    }
#endif // QT_NO_PROPERTIES
    return _id;
}
int ONVIF::VideoEncoderConfiguration::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
    _id = QObject::qt_metacall(_c, _id, _a);
    if (_id < 0)
        return _id;
    if (_c == QMetaObject::InvokeMetaMethod) {
        if (_id < 19)
            qt_static_metacall(this, _c, _id, _a);
        _id -= 19;
    } else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
        if (_id < 19)
            *reinterpret_cast<int*>(_a[0]) = -1;
        _id -= 19;
    }
#ifndef QT_NO_PROPERTIES
      else if (_c == QMetaObject::ReadProperty) {
        void *_v = _a[0];
        switch (_id) {
        case 0: *reinterpret_cast< QString*>(_v) = token(); break;
        case 1: *reinterpret_cast< QString*>(_v) = name(); break;
        case 2: *reinterpret_cast< int*>(_v) = useCount(); break;
        case 3: *reinterpret_cast< QString*>(_v) = encoding(); break;
        case 4: *reinterpret_cast< int*>(_v) = width(); break;
        case 5: *reinterpret_cast< int*>(_v) = height(); break;
        case 6: *reinterpret_cast< int*>(_v) = quality(); break;
        case 7: *reinterpret_cast< int*>(_v) = frameRateLimit(); break;
        case 8: *reinterpret_cast< int*>(_v) = encodingInterval(); break;
        case 9: *reinterpret_cast< int*>(_v) = bitrateLimit(); break;
        case 10: *reinterpret_cast< int*>(_v) = govLength(); break;
        case 11: *reinterpret_cast< QString*>(_v) = h264Profile(); break;
        case 12: *reinterpret_cast< QString*>(_v) = type(); break;
        case 13: *reinterpret_cast< QString*>(_v) = ipv4Address(); break;
        case 14: *reinterpret_cast< QString*>(_v) = ipv6Address(); break;
        case 15: *reinterpret_cast< int*>(_v) = port(); break;
        case 16: *reinterpret_cast< int*>(_v) = ttl(); break;
        case 17: *reinterpret_cast< bool*>(_v) = autoStart(); break;
        case 18: *reinterpret_cast< QString*>(_v) = sessionTimeout(); break;
        default: break;
        }
        _id -= 19;
    } else if (_c == QMetaObject::WriteProperty) {
        void *_v = _a[0];
        switch (_id) {
        case 0: setToken(*reinterpret_cast< QString*>(_v)); break;
        case 1: setName(*reinterpret_cast< QString*>(_v)); break;
        case 2: setUseCount(*reinterpret_cast< int*>(_v)); break;
        case 3: setEncoding(*reinterpret_cast< QString*>(_v)); break;
        case 4: setWidth(*reinterpret_cast< int*>(_v)); break;
        case 5: setHeight(*reinterpret_cast< int*>(_v)); break;
        case 6: setQuality(*reinterpret_cast< int*>(_v)); break;
        case 7: setFrameRateLimit(*reinterpret_cast< int*>(_v)); break;
        case 8: setEncodingInterval(*reinterpret_cast< int*>(_v)); break;
        case 9: setBitrateLimit(*reinterpret_cast< int*>(_v)); break;
        case 10: setGovLength(*reinterpret_cast< int*>(_v)); break;
        case 11: setH264Profile(*reinterpret_cast< QString*>(_v)); break;
        case 12: setType(*reinterpret_cast< QString*>(_v)); break;
        case 13: setIpv4Address(*reinterpret_cast< QString*>(_v)); break;
        case 14: setIpv6Address(*reinterpret_cast< QString*>(_v)); break;
        case 15: setPort(*reinterpret_cast< int*>(_v)); break;
        case 16: setTtl(*reinterpret_cast< int*>(_v)); break;
        case 17: setAutoStart(*reinterpret_cast< bool*>(_v)); break;
        case 18: setSessionTimeout(*reinterpret_cast< QString*>(_v)); break;
        default: break;
        }
        _id -= 19;
    } else if (_c == QMetaObject::ResetProperty) {
        _id -= 19;
    } else if (_c == QMetaObject::QueryPropertyDesignable) {
        _id -= 19;
    } else if (_c == QMetaObject::QueryPropertyScriptable) {
        _id -= 19;
    } else if (_c == QMetaObject::QueryPropertyStored) {
        _id -= 19;
    } else if (_c == QMetaObject::QueryPropertyEditable) {
        _id -= 19;
    } else if (_c == QMetaObject::QueryPropertyUser) {
        _id -= 19;
    } else if (_c == QMetaObject::RegisterPropertyMetaType) {
        if (_id < 19)
            *reinterpret_cast<int*>(_a[0]) = -1;
        _id -= 19;
    }
#endif // QT_NO_PROPERTIES
    return _id;
}