summaryrefslogtreecommitdiff
path: root/src/main/kotlin/NetworkPacketTransporter.kt
blob: 4b119677e3a6c11c557426798342e5b7d706a8b5 (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
import java.io.Closeable

/**
 * [NetworkPacketTransporter] is an abstract class for network transport-layer operations. A class that implements this
 * class' abstract methods, once instantiated, establishes and manages a connection with a remote endpoint defined by an
 * address and a port and allows to send and receive network messages (also called "payloads").
 *
 * The address of the remote endpoint can be an IP address (v4 or v6) or a domain name, in which case it is resolved to
 * an IP address right before initializing the connection. Every constructor should throw an [UnresolvableHostException]
 * if the remote address is a domain name, but it cannot be resolved.
 *
 * Depending on the specific given implementation, the constructor of this class might throw other exceptions (e.g. the
 * [Socket] constructor from [java.net] in [NetworkPacketTransporterJavaNet]).
 */
abstract class NetworkPacketTransporter : Closeable {
    val address: String
    val port: UShort

    /**
     * Classic constructor.
     *
     * @throws UnresolvableHostException if the remote address is a domain name, but it cannot be resolved.
     */
    constructor(address: String, port: UShort) {
        this.address = address
        this.port = port
    }

    /**
     * This constructor allows addresses specified using one of the styles specified in dial(2). See
     * [nineAddressToValues].
     *
     * @throws UnresolvableHostException if the remote address is a domain name, but it cannot be resolved.
     */
    constructor(fullAddress: String) {
        val ap = nineAddressToValues(fullAddress)
        this.address = ap.first
        this.port = ap.second
    }

    /**
     * Close the connection.
     */
    abstract override fun close()

    /**
     * Transmit a payload.
     *
     * @throws java.io.IOException if the message could not be correctly transmitted.
     */
    abstract fun transmit(payload: List<Byte>)

    /**
     * Receive a payload until a byte occurs, which marks the end of the message. The byte is discarded after being read
     * and is not returned.
     *
     * If you know both which byte marks the end of the message and the message length, it is advised to use
     * [receiveFixed] instead, which is usually more efficient.
     *
     * @param untilByte The byte that marks the end of the message.
     *
     * @throws java.io.IOException if the message could not be correctly received.
     */
    abstract fun receiveUntil(untilByte: Byte): List<Byte>

    /**
     * Receive a payload with fixed length.
     *
     * @param length The length of the message in bytes.
     *
     * @throws java.io.IOException if the message could not be correctly received.
     */
    abstract fun receiveFixed(length: ULong): List<Byte>
}