138 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			138 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			C++
		
	
	
	
| // PHZ
 | |
| // 2018-5-15
 | |
| 
 | |
| #include "BufferWriter.h"
 | |
| #include "Socket.h"
 | |
| #include "SocketUtil.h"
 | |
| 
 | |
| using namespace xop;
 | |
| 
 | |
| void xop::WriteUint32BE(char* p, uint32_t value)
 | |
| {
 | |
| 	p[0] = value >> 24;
 | |
| 	p[1] = value >> 16;
 | |
| 	p[2] = value >> 8;
 | |
| 	p[3] = value & 0xff;
 | |
| }
 | |
| 
 | |
| void xop::WriteUint32LE(char* p, uint32_t value)
 | |
| {
 | |
| 	p[0] = value & 0xff;
 | |
| 	p[1] = value >> 8;
 | |
| 	p[2] = value >> 16;
 | |
| 	p[3] = value >> 24;
 | |
| }
 | |
| 
 | |
| void xop::WriteUint24BE(char* p, uint32_t value)
 | |
| {
 | |
| 	p[0] = value >> 16;
 | |
| 	p[1] = value >> 8;
 | |
| 	p[2] = value & 0xff;
 | |
| }
 | |
| 
 | |
| void xop::WriteUint24LE(char* p, uint32_t value)
 | |
| {
 | |
| 	p[0] = value & 0xff;
 | |
| 	p[1] = value >> 8;
 | |
| 	p[2] = value >> 16;
 | |
| }
 | |
| 
 | |
| void xop::WriteUint16BE(char* p, uint16_t value)
 | |
| {
 | |
| 	p[0] = value >> 8;
 | |
| 	p[1] = value & 0xff;
 | |
| }
 | |
| 
 | |
| void xop::WriteUint16LE(char* p, uint16_t value)
 | |
| {
 | |
| 	p[0] = value & 0xff;
 | |
| 	p[1] = value >> 8;
 | |
| }
 | |
| 
 | |
| BufferWriter::BufferWriter(int capacity) 
 | |
| 	: max_queue_length_(capacity)
 | |
| {
 | |
| 	
 | |
| }	
 | |
| 
 | |
| bool BufferWriter::Append(std::shared_ptr<char> data, uint32_t size, uint32_t index)
 | |
| {
 | |
| 	if (size <= index) {
 | |
| 		return false;
 | |
| 	}
 | |
|    
 | |
| 	if ((int)buffer_.size() >= max_queue_length_) {
 | |
| 		return false;
 | |
| 	}
 | |
|      
 | |
| 	Packet pkt = { data, size, index };
 | |
| 	buffer_.emplace(std::move(pkt));
 | |
| 	return true;
 | |
| }
 | |
| 
 | |
| bool BufferWriter::Append(const char* data, uint32_t size, uint32_t index)
 | |
| {
 | |
| 	if (size <= index) {
 | |
| 		return false;
 | |
| 	}
 | |
|      
 | |
| 	if ((int)buffer_.size() >= max_queue_length_) {
 | |
| 		return false;
 | |
| 	}
 | |
|      
 | |
| 	Packet pkt;
 | |
| 	pkt.data.reset(new char[size+512]);
 | |
| 	memcpy(pkt.data.get(), data, size);
 | |
| 	pkt.size = size;
 | |
| 	pkt.writeIndex = index;
 | |
| 	buffer_.emplace(std::move(pkt));
 | |
| 	return true;
 | |
| }
 | |
| 
 | |
| int BufferWriter::Send(SOCKET sockfd, int timeout)
 | |
| {		
 | |
| 	if (timeout > 0) {
 | |
| 		SocketUtil::SetBlock(sockfd, timeout); 
 | |
| 	}
 | |
|       
 | |
| 	int ret = 0;
 | |
| 	int count = 1;
 | |
| 
 | |
| 	do
 | |
| 	{
 | |
| 		if (buffer_.empty()) {
 | |
| 			return 0;
 | |
| 		}
 | |
| 		
 | |
| 		count -= 1;
 | |
| 		Packet &pkt = buffer_.front();
 | |
| 		ret = ::send(sockfd, pkt.data.get() + pkt.writeIndex, pkt.size - pkt.writeIndex, 0);
 | |
| 		if (ret > 0) {
 | |
| 			pkt.writeIndex += ret;
 | |
| 			if (pkt.size == pkt.writeIndex) {
 | |
| 				count += 1;
 | |
| 				buffer_.pop();
 | |
| 			}
 | |
| 		}
 | |
| 		else if (ret < 0) {
 | |
| #if defined(__linux) || defined(__linux__)
 | |
| 		if (errno == EINTR || errno == EAGAIN) 
 | |
| #elif defined(WIN32) || defined(_WIN32)
 | |
| 			int error = WSAGetLastError();
 | |
| 			if (error == WSAEWOULDBLOCK || error == WSAEINPROGRESS || error == 0)
 | |
| #endif
 | |
| 			{
 | |
| 				ret = 0;
 | |
| 			}
 | |
| 		}
 | |
| 	} while (count > 0);
 | |
| 
 | |
| 	if (timeout > 0) {
 | |
| 		SocketUtil::SetNonBlock(sockfd);
 | |
| 	}
 | |
|     
 | |
| 	return ret;
 | |
| }
 | |
| 
 | |
| 
 |