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 }