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;
}
Example #2
0
void MsgEdit::makeMessage()
{
    if (msg == NULL) return;
    switch (msg->Type()){
    case ICQ_MSGxMSG:{
            ICQMsg *m = static_cast<ICQMsg*>(msg);
            m->Message = edit->text().local8Bit();
            if (edit->colorChanged()){
                m->BackColor = (edit->background().rgb() & 0xFFFFFF);
                m->ForeColor = (edit->foreground().rgb() & 0xFFFFFF);
                pMain->MessageBgColor = m->BackColor();
                pMain->MessageFgColor = m->ForeColor();
            }
            break;
        }
    case ICQ_MSGxURL:{
            ICQUrl *m = static_cast<ICQUrl*>(msg);
            m->Message = edit->text().local8Bit();
            m->URL = urlEdit->text().local8Bit();
            break;
        }
    case ICQ_MSGxFILE:{
            ICQFile *m = static_cast<ICQFile*>(msg);
            m->Description = edit->text().local8Bit();
            m->Name = fileEdit->text().local8Bit();
            break;
        }
    case ICQ_MSGxCHAT:{
            ICQChat *m = static_cast<ICQChat*>(msg);
            m->Reason = edit->text().local8Bit();
            break;
        }
    case ICQ_MSGxSMS:{
            ICQSMS *m = static_cast<ICQSMS*>(msg);
            string s;
            s = edit->text().local8Bit();
            s = pClient->clearHTML(s.c_str());
            msgTail = trim(QString::fromLocal8Bit(s.c_str()));
            m->Message = smsChunk();
            m->Phone = phoneEdit->lineEdit()->text().local8Bit();
            break;
        }
    case ICQ_MSGxCONTACTxLIST:{
            ICQContacts *m = static_cast<ICQContacts*>(msg);
            users->fillList(m->Contacts);
            break;
        }
    case ICQ_MSGxAUTHxREQUEST:{
            ICQAuthRequest *m = static_cast<ICQAuthRequest*>(msg);
            m->Message = edit->text().local8Bit();
            break;
        }
    case ICQ_MSGxAUTHxREFUSED:{
            ICQAuthRefused *m = static_cast<ICQAuthRefused*>(msg);
            m->Message = edit->text().local8Bit();
            break;
        }
    case ICQ_MSGxAUTHxGRANTED:
        break;
    default:
        log(L_WARN, "Bad message type %u", msg->Type());
        return;
    }
    if (bMultiply){
        msg->Uin.clear();
        UserBox *box = static_cast<UserBox*>(topLevelWidget());
        if (box->users){
            UserView *users = box->users;
            if (users) users->fillChecked(msg);
        }
    }
    realSend();
}