blob: ee1c9f9f13b4b823ecf314369542ef4f7742c572 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
import java.io.InputStream
import java.io.OutputStream
import java.net.Socket
import kotlin.math.min
/*
TODO:
- add TLS support
*/
/**
* An implementation of [TransportLayer] written using the [java.net] package.
*/
class TransportLayerJavaNet(val address: String, val port: UShort) : TransportLayer {
/**
* The connection's socket.
*/
private val socket: Socket = Socket(this.address, this.port.toInt())
/**
* The connection's input stream.
*/
private val inStream: InputStream = this.socket.inputStream
/**
* The connection's output stream.
*/
private val outStream: OutputStream = this.socket.outputStream
constructor(fullAddress: String) : this(nineAddressToValues(fullAddress).first, nineAddressToValues(fullAddress).second)
private class InStreamIterator(val inStream: InputStream) : Iterator<UByte> {
override fun next(): UByte {
return this.inStream.readNBytes(1).first().toUByte()
}
override fun hasNext(): Boolean {
return this.inStream.available() > 0
}
}
override fun close() {
if (this.socket.isClosed) {
return
}
this.socket.close()
}
override fun transmit(payload: Iterable<UByte>) {
val payload = payload.toList()
val bytes = ByteArray(payload.size, { i -> payload[i].toByte() })
this.outStream.write(bytes)
}
/*
override fun receiveUntil(untilByte: UByte): Array<UByte> {
var stop = false
val payload: Array<UByte> = MutableList(0, { 0 })
while (!stop) {
val b = this.inStream.readNBytes(1)[0]
if (b == untilByte) {
stop = true
continue
} else {
payload.add(b)
}
}
return payload
}
*/
override fun receive(length: ULong): Array<UByte> {
var length = length
val intMax = Int.MAX_VALUE.toULong()
val bytes: MutableList<Byte> = MutableList(0) { 0 }
// readNBytes only takes Int values, so it must be called multiple times if the length is greater than Int's
// maximum value
while (length > 0u) {
// the min function ensures that the value passed to readNBytes never exceeds Int's maximum value while also
// switching to the length variable when its value eventually becomes less than Int's maximum value, which
// avoids writing duplicated readNBytes calls in the code
val lenMin = min(length, intMax)
bytes += this.inStream.readNBytes(lenMin.toInt()).toMutableList()
length -= intMax
}
return Array(bytes.size) { i -> bytes[i].toUByte() }
}
override fun receiver(): Iterable<UByte> {
return Iterable { InStreamIterator(this.inStream) }
}
}
|