1 module bmessage;
2 
3 import std.socket : Socket, SocketFlags, MSG_WAITALL;
4 
5 public byte[] decodeMessage(byte[] bformatBytes)
6 {
7 	/* Construct a buffer to receive into */
8 	byte[] receiveBuffer;
9 
10 	/* Get the length of the message */
11 	byte[4] messageLengthBytes = bformatBytes[0..4];
12 
13 	/* Response message length */
14 	uint messageLength;
15 
16 	/* Little endian version you simply read if off the bone (it's already in the correct order) */
17 	version(LittleEndian)
18 	{
19 		messageLength = *cast(int*)messageLengthBytes.ptr;
20 	}
21 
22 	/* Big endian requires we byte-sapped the little-endian encoded number */
23 	version(BigEndian)
24 	{
25 		byte[] swappedLength;
26 		swappedLength.length = 4;
27 
28 		swappedLength[0] = messageLengthBytes[3];
29 		swappedLength[1] = messageLengthBytes[2];
30 		swappedLength[2] = messageLengthBytes[1];
31 		swappedLength[3] = messageLengthBytes[0];
32 
33 		messageLength = *cast(int*)swappedLength.ptr;
34 	}
35 
36 
37 	/* Read the full message */
38 	receiveBuffer = bformatBytes[4..4+messageLength];
39 
40 	return receiveBuffer;
41 }
42 
43 public bool receiveMessage(Socket originator, ref byte[] receiveMessage)
44 {
45 	/* Construct a buffer to receive into */
46 	byte[] receiveBuffer;
47 
48 	bool status = true;
49 
50 
51 	/* The amount of bytes received */
52 	long bytesReceived;
53 
54 	/* Get the length of the message */
55 	byte[4] messageLengthBytes;
56 	bytesReceived = originator.receive(messageLengthBytes, cast(SocketFlags)MSG_WAITALL);
57 
58 	/* If there was an error reading from the socket */
59 	if(!(bytesReceived > 0))
60 	{
61 		status =  false;
62 	}
63 	/* If the receive was successful */
64 	else
65 	{
66 		/* Response message length */
67 		uint messageLength;
68 
69 		/* Little endian version you simply read if off the bone (it's already in the correct order) */
70 		version(LittleEndian)
71 		{
72 			messageLength = *cast(int*)messageLengthBytes.ptr;
73 		}
74 
75 		/* Big endian requires we byte-sapped the little-endian encoded number */
76 		version(BigEndian)
77 		{
78 			byte[] swappedLength;
79 			swappedLength.length = 4;
80 
81 			swappedLength[0] = messageLengthBytes[3];
82 			swappedLength[1] = messageLengthBytes[2];
83 			swappedLength[2] = messageLengthBytes[1];
84 			swappedLength[3] = messageLengthBytes[0];
85 
86 			messageLength = *cast(int*)swappedLength.ptr;
87 		}
88 
89 
90 		/* Read the full message */
91 		receiveBuffer.length = messageLength;
92 		bytesReceived = originator.receive(receiveBuffer, cast(SocketFlags)MSG_WAITALL);
93 
94 		/* If there was an error reading from the socket */
95 		if(!(bytesReceived > 0))
96 		{
97 			status = false;
98 		}
99 		/* If there was no error receiving the message */
100 		else
101 		{
102 			receiveMessage = receiveBuffer;
103 		}
104 	}
105 
106 	return status;
107 }
108 
109 public byte[] encodeBformat(byte[] message)
110 {
111 	/* The message buffer */
112 	byte[] messageBuffer;
113 
114 	/* Encode the 4 byte message length header (little endian) */
115 	int payloadLength = cast(int)message.length;
116 	byte* lengthBytes = cast(byte*)&payloadLength;
117 
118 	/* On little endian simply get the bytes as is (it would be encoded as little endian) */
119 	version(LittleEndian)
120 	{
121 		messageBuffer ~= *(lengthBytes+0);
122 		messageBuffer ~= *(lengthBytes+1);
123 		messageBuffer ~= *(lengthBytes+2);
124 		messageBuffer ~= *(lengthBytes+3);
125 	}
126 
127 	/* On Big Endian you must swap the big-endian-encoded number to be in little endian ordering */
128 	version(BigEndian)
129 	{
130 		messageBuffer ~= *(lengthBytes+3);
131 		messageBuffer ~= *(lengthBytes+2);
132 		messageBuffer ~= *(lengthBytes+1);
133 		messageBuffer ~= *(lengthBytes+0);
134 	}
135 	
136 
137 	/* Add the message to the buffer */
138 	messageBuffer ~= cast(byte[])message;
139 
140 	return messageBuffer;
141 }
142 
143 public bool sendMessage(Socket recipient, byte[] message)
144 {
145 	/* The message buffer */
146 	byte[] messageBuffer;
147 
148 	/* Encode the 4 byte message length header (little endian) */
149 	int payloadLength = cast(int)message.length;
150 	byte* lengthBytes = cast(byte*)&payloadLength;
151 
152 	/* On little endian simply get the bytes as is (it would be encoded as little endian) */
153 	version(LittleEndian)
154 	{
155 		messageBuffer ~= *(lengthBytes+0);
156 		messageBuffer ~= *(lengthBytes+1);
157 		messageBuffer ~= *(lengthBytes+2);
158 		messageBuffer ~= *(lengthBytes+3);
159 	}
160 
161 	/* On Big Endian you must swap the big-endian-encoded number to be in little endian ordering */
162 	version(BigEndian)
163 	{
164 		messageBuffer ~= *(lengthBytes+3);
165 		messageBuffer ~= *(lengthBytes+2);
166 		messageBuffer ~= *(lengthBytes+1);
167 		messageBuffer ~= *(lengthBytes+0);
168 	}
169 	
170 
171 	/* Add the message to the buffer */
172 	messageBuffer ~= cast(byte[])message;
173 
174 	/* Send the message */
175 	long bytesSent = recipient.send(messageBuffer);
176 
177 	/* TODO: Compact this */
178 	return bytesSent > 0;
179 }