1 /** 2 * Socket encoding/decoding functions 3 */ 4 module bformat.sockets; 5 6 import std.socket : Socket, SocketFlags, MSG_WAITALL; 7 8 /** 9 * Receives a message from the provided socket 10 * by decoding the streamed bytes into bformat 11 * and finally placing the resulting payload in 12 * the provided array 13 * 14 * Params: 15 * originator = the socket to receive from 16 * receiveMessage = the nbuffer to receive into 17 * 18 * Returns: true if the receive succeeded, false otheriwse 19 */ 20 public bool receiveMessage(Socket originator, ref byte[] receiveMessage) 21 { 22 /* Construct a buffer to receive into */ 23 byte[] receiveBuffer; 24 25 bool status = true; 26 27 28 /* The amount of bytes received */ 29 long bytesReceived; 30 31 /* Get the length of the message */ 32 byte[4] messageLengthBytes; 33 bytesReceived = originator.receive(messageLengthBytes, cast(SocketFlags)MSG_WAITALL); 34 35 /* If there was an error reading from the socket */ 36 if(!(bytesReceived > 0)) 37 { 38 status = false; 39 } 40 /* If the receive was successful */ 41 else 42 { 43 /* Response message length */ 44 uint messageLength; 45 46 /* Little endian version you simply read if off the bone (it's already in the correct order) */ 47 version(LittleEndian) 48 { 49 messageLength = *cast(int*)messageLengthBytes.ptr; 50 } 51 52 /* Big endian requires we byte-sapped the little-endian encoded number */ 53 version(BigEndian) 54 { 55 byte[] swappedLength; 56 swappedLength.length = 4; 57 58 swappedLength[0] = messageLengthBytes[3]; 59 swappedLength[1] = messageLengthBytes[2]; 60 swappedLength[2] = messageLengthBytes[1]; 61 swappedLength[3] = messageLengthBytes[0]; 62 63 messageLength = *cast(int*)swappedLength.ptr; 64 } 65 66 67 /* Read the full message */ 68 receiveBuffer.length = messageLength; 69 bytesReceived = originator.receive(receiveBuffer, cast(SocketFlags)MSG_WAITALL); 70 71 /* If there was an error reading from the socket */ 72 if(!(bytesReceived > 0)) 73 { 74 status = false; 75 } 76 /* If there was no error receiving the message */ 77 else 78 { 79 receiveMessage = receiveBuffer; 80 } 81 } 82 83 return status; 84 } 85 86 /** 87 * Encodes the provided message into the bformat format 88 * and sends it over the provided socket 89 * 90 * Params: 91 * recipient = the socket to send over 92 * message = the message to encode and send 93 * 94 * Returns: true if the send succeeded, false otherwise 95 */ 96 public bool sendMessage(Socket recipient, byte[] message) 97 { 98 /* The message buffer */ 99 byte[] messageBuffer; 100 101 /* Encode the 4 byte message length header (little endian) */ 102 int payloadLength = cast(int)message.length; 103 byte* lengthBytes = cast(byte*)&payloadLength; 104 105 /* On little endian simply get the bytes as is (it would be encoded as little endian) */ 106 version(LittleEndian) 107 { 108 messageBuffer ~= *(lengthBytes+0); 109 messageBuffer ~= *(lengthBytes+1); 110 messageBuffer ~= *(lengthBytes+2); 111 messageBuffer ~= *(lengthBytes+3); 112 } 113 114 /* On Big Endian you must swap the big-endian-encoded number to be in little endian ordering */ 115 version(BigEndian) 116 { 117 messageBuffer ~= *(lengthBytes+3); 118 messageBuffer ~= *(lengthBytes+2); 119 messageBuffer ~= *(lengthBytes+1); 120 messageBuffer ~= *(lengthBytes+0); 121 } 122 123 124 /* Add the message to the buffer */ 125 messageBuffer ~= cast(byte[])message; 126 127 /* Send the message */ 128 long bytesSent = recipient.send(messageBuffer); 129 130 /* TODO: Compact this */ 131 return bytesSent > 0; 132 }