1 module libchonky;
2 
3 /**
4 * libchonky
5 *
6 *
7 */
8 
9 import std.socket;
10 import core.sys.posix.sys.socket;
11 
12 public final class ChonkReader
13 {
14 	/* The socket to read from */
15 	private Socket socket;
16 	private ptrdiff_t chunkSize;
17 
18 	this(Socket socket, ptrdiff_t chunkSize = 50)
19 	{
20 		/* THe socket must in STREAM mode */
21 		/* TODO */
22 		
23 		/* Save the socket */
24 		this.socket = socket;
25 		
26 		/* Set the chunk size */
27 		this.chunkSize = chunkSize;
28 	}
29 
30 	/**
31 	* Read the amount given by the size of the buffer
32 	* This uses MSG_WAITALL and will only return when
33 	* the full amount bytes requested is fulfilled,
34 	* not just the currently available amount in the
35 	* kernel network queue
36 	*
37 	* Number of bytes received `0` if socket closed
38 	* (follow the normal D-standard) or Socket.ERROR
39 	*
40 	* ptrdiff_t is signed (long -> int, depending on arch (compiler time))
41 	*/
42 	public ptrdiff_t receiveAll(byte[] buffer)
43 	{
44 		/* Enable `MSG_WAITALL` flag */
45 		SocketFlags flags = cast(SocketFlags)MSG_WAITALL;
46 
47 
48 		return socket.receive(buffer, flags);
49 	} 
50 
51 
52 	/**
53 	* Some applications have no header for length but
54 	* demarcate the data ending by closing the socket
55 	* here one would want to chunk read as making
56 	* an assumption about how much data is sent would
57 	* be futile
58 	*
59 	* This will read in chunks of `chunkSize` whilst
60 	* stiching an array toghether. It will take in
61 	* a pointer to (len, ptr) (a.k.a. an array)
62 	* and set those for you.
63 	*
64 	* The total number of bytes is returned
65 	*/
66 	public ulong receiveUntilClose(ref byte[] buffer)
67 	{
68 		/* Temporary array */
69 		byte[] temp;
70 		temp.length=chunkSize;
71 		ulong bytesReceived;
72 
73 		while(true)
74 		{
75 			/* Receive chunk many bytes */
76 			ptrdiff_t byteCount = receiveAll(temp);
77 
78 			/* Ending (0 is closed socket, and I believe anything less would then be other errors) */
79 			if(byteCount <= 0)
80 			{
81 				break;
82 			}
83 			else
84 			{
85 				buffer ~= temp[0..byteCount];
86 				bytesReceived = bytesReceived + byteCount;
87 			}
88 		}
89 		/* TODO: Implement me */
90 		return bytesReceived;
91 	}
92 }