1 module connection.message;
2 
3 import std.socket : Socket, SocketFlags;
4 import std.json : JSONValue, parseJSON, toJSON;
5 import utils.debugging : debugPrint;
6 import std.stdio : writeln;
7 
8 /**
9  * Generalized socket receive function which will read into the
10  * variable pointed to by `receiveMessage` by reading from the
11  * socket `originator`.
12  */
13 public static void receiveMessage(Socket originator, ref JSONValue receiveMessage)
14 {
15 	/* TODO: Implement me */
16 
17 	/* Construct a buffer to receive into */
18 	byte[] receiveBuffer;
19 
20 	/* The current byte */
21 	uint currentByte = 0;
22 
23 	/* The amount of bytes received */
24 	long bytesReceived;
25 
26 	/* Loop consume the next 4 bytes */
27 	while(currentByte < 4)
28 	{
29 		/* Temporary buffer */
30 		byte[4] tempBuffer;
31 
32 		/* Read at-most 4 bytes */
33 		bytesReceived = originator.receive(tempBuffer);
34 
35 		/* If there was an error reading from the socket */
36 		if(!(bytesReceived > 0))
37 		{
38 			/* TODO: Error handling */
39 			debugPrint("Error receiving from socket");
40 		}
41 		/* If there is no error reading from the socket */
42 		else
43 		{
44 			/* Add the read bytes to the *real* buffer */
45 			receiveBuffer ~= tempBuffer[0..bytesReceived];
46 
47 			/* Increment the byte counter */
48 			currentByte += bytesReceived;
49 		}
50 	}
51 
52 	/* Response message length */
53 	int messageLength = *cast(int*)receiveBuffer.ptr;
54 	writeln("Message length is: ", cast(uint)messageLength);
55 
56 	/* Response message buffer */
57 	byte[] fullMessage;
58 
59 	/* Reset the byte counter */
60 	currentByte = 0;
61 
62 	while(currentByte < messageLength)
63 	{
64 		debugPrint("dhjkh");
65 
66 		/**
67 		 * Receive 20 bytes (at most) at a time and don't dequeue from
68 		 * the kernel's TCP stack's buffer.
69 		 */
70 		byte[20] tempBuffer;
71 		bytesReceived = originator.receive(tempBuffer, SocketFlags.PEEK);
72 
73 		/* Check for an error whilst receiving */
74 		if(!(bytesReceived > 0))
75 		{
76 			/* TODO: Error handling */
77 			debugPrint("Error whilst receiving from socket");
78 		}
79 		else
80 		{
81 			/* TODO: Make sure we only take [0, messageLength) bytes */
82 			if(cast(uint)bytesReceived+currentByte > messageLength)
83 			{
84 				byte[] remainingBytes;
85 				remainingBytes.length = messageLength-currentByte;
86 
87 				originator.receive(remainingBytes);
88 
89 				/* Increment counter of received bytes */
90 				currentByte += remainingBytes.length;
91 
92 				/* Append the received bytes to the FULL message buffer */
93 				fullMessage ~= remainingBytes;
94 
95 				writeln("Received ", currentByte, "/", cast(uint)messageLength, " bytes");
96 			}
97 			else
98 			{
99 				/* Increment counter of received bytes */
100 				currentByte += bytesReceived;
101 
102 						
103 				/* Append the received bytes to the FULL message buffer */
104 				fullMessage ~= tempBuffer[0..bytesReceived];
105 
106 				/* TODO: Bug when over send, we must not allow this */
107 
108 						
109 				writeln("Received ", currentByte, "/", cast(uint)messageLength, " bytes");	
110 
111 				originator.receive(tempBuffer);
112 			}
113 		}
114 	}
115 
116 	writeln("Message ", fullMessage);
117 
118 	/* Set the message in `receiveMessage */
119 	receiveMessage = parseJSON(cast(string)fullMessage);
120 }
121 
122 /**
123  * Generalized socket send function which will send the JSON
124  * encoded message, `jsonMessage`, over to the client at the
125  * other end of the socket, `recipient`.
126  *
127  * It gets the length of `jsonMessage` and encodes a 4 byte
128  * message header in little-endian containing the message's
129  * length.
130  */
131 public static void sendMessage(Socket recipient, JSONValue jsonMessage)
132 {
133 	/* The message buffer */
134 	byte[] messageBuffer;
135 
136 	/* Get the JSON as a string */
137 	string message = toJSON(jsonMessage);
138 
139 	/* Encode the 4 byte message length header (little endian) */
140 	int payloadLength = cast(int)message.length;
141 	byte* lengthBytes = cast(byte*)&payloadLength;
142 	messageBuffer ~= *(lengthBytes+0);
143 	messageBuffer ~= *(lengthBytes+1);
144 	messageBuffer ~= *(lengthBytes+2);
145 	messageBuffer ~= *(lengthBytes+3);
146 
147 	/* Add the message to the buffer */
148 	messageBuffer ~= cast(byte[])message;
149 
150 	/* Send the message */
151 	recipient.send(messageBuffer);
152 }