With 5.1.1f1 PC, how would we get into a state with the HLAPI where the LLAPI thinks we are trying to send 0 bytes via NetworkServer.SendWriterToReady(null, writer, 2);?
We check that the writer always has more than 0 bytes before we send the message.
This repeats for a long time on our server:
2015-09-09 17:39:33.699+00:00 [ERR] Cannot send message of 0 bytes length
2015-09-09 17:39:33.699+00:00 [ERR] Failed to send internal buffer conn:1 channel:2 bytesToSend:0
2015-09-09 17:39:33.700+00:00 [ERR] Send Error: 5 conn:1 channel:2 bytesToSend:0
2015-09-09 17:39:33.706+00:00 [ERR] Cannot send message of 0 bytes length
2015-09-09 17:39:33.706+00:00 [ERR] Failed to send internal buffer conn:1 channel:2 bytesToSend:0
2015-09-09 17:39:33.707+00:00 [ERR] Send Error: 5 conn:1 channel:2 bytesToSend:0
…
(error 5 == NetworkError.BadMessage, which the doc comments read “Obsolete”)
I think if you send a packet of exactly max packet size, you could get this error, although I am not sure it is our issue.
in ChannelBuffer.SendBytes, if bytesToSend == this.m_maxPacketSize, then this.m_CurrentPacket.HasSpace will always fail for an empty current packet, due to the this.m_position + numBytes < this.m_buffer.Length check. Then, if it’s a reliable channel, and there are no pending packets, it will attempt to send the empty current packet before writing the maxPacketSize argument to SendBytes.
The send of the zero byte current packet will always fail, and queue itself again to send and send, which may be problematic if there is a send delay, not to mention the error spam.
A more common bug is just that ChannelPacket.SendToTransport sets the m_position to 0 in cases where the NetworkTransport.Send failed, and then that packet is queued to the pending packets, and will then fail for ever. This doesn’t seem to be our issue, as we never see the error “Failed to send internal buffer conn:” with more than zero bytes.
It looks like 5.1.1f1, 5.1.3f1 and 5.2.0f2 are affected, so I hope I am wrong about this
by the way, we were getting this with a ReliableFragmented channel, I’ve told my team to just use ReliableSequenced for now, as the reliability for failed sends on ReliableFragmented is not fully implemented