summaryrefslogtreecommitdiffstats
path: root/jrt/src/com/yahoo/jrt/CryptoSocket.java
blob: 78308b76624b7dce60442045833339e80bc701c5 (plain) (blame)
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.jrt;


import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.Optional;


/**
 * Abstraction of a low-level async network socket which can produce
 * io events and allows encrypting written data and decrypting read
 * data. The interface is complexified to handle the use of internal
 * buffers that may mask io events and pending work. The interface is
 * simplified by assuming there will be no mid-stream re-negotiation
 * (no read/write cross-dependencies). Handshaking is explicit and
 * up-front. This interface is initially designed for persistent
 * transport connections where closing the connection has no
 * application-level semantics.
 **/
public interface CryptoSocket {

    /**
     * Obtain the underlying socket channel used by this CryptoSocket.
     **/
    public SocketChannel channel();

    public enum HandshakeResult { DONE, NEED_READ, NEED_WRITE, NEED_WORK }

    /**
     * Try to progress the initial connection handshake. Handshaking
     * will be done once, before any normal reads or writes are
     * performed. Re-negotiation at a later stage will not be
     * permitted. This function will be called multiple times until
     * the status is either DONE or an IOException is thrown. When
     * NEED_READ or NEED_WRITE is returned, the handshake function
     * will be called again when the appropriate io event has
     * triggered. When NEED_WORK is returned, the {@link #doHandshakeWork()}
     * will be called (possibly in another thread) before this function is called again.
     **/
    public HandshakeResult handshake() throws IOException;


    /**
     * Called when {@link #handshake()} returns {@link HandshakeResult#NEED_WORK} to perform compute-heavy tasks.
     * This method may be called from another thread to avoid blocking the transport thread.
     */
    public void doHandshakeWork();

    /**
     * This function should be called after handshaking has completed
     * before calling the read function. It dictates the minimum size
     * of the application read buffer presented to the read
     * function. This is needed to support frame-based stateless
     * decryption of incoming data.
     **/
    public int getMinimumReadBufferSize();

    /**
     * Called when the underlying socket has available data. Read
     * through the entire input pipeline. The semantics are the same
     * as with a normal socket read except it can also fail for
     * cryptographic reasons.
     **/
    public int read(ByteBuffer dst) throws IOException;

    /**
     * Similar to read, but this function is not allowed to read from
     * the underlying socket. This is to enable the application to
     * make sure that there is no more input data in the read pipeline
     * that is independent of data not yet read from the actual
     * socket. Draining data from the input pipeline is done to
     * prevent masking read events.
     **/
    public int drain(ByteBuffer dst) throws IOException;

    /**
     * Called when the application has data it wants to write. Write
     * through the entire output pipeline. The semantics are the same
     * as with a normal socket write.
     **/
    public int write(ByteBuffer src) throws IOException;

    public enum FlushResult { DONE, NEED_WRITE }

    /**
     * Try to flush data in the write pipeline that is not depenedent
     * on data not yet written by the application into the underlying
     * socket. This is to enable the application to identify pending
     * work that may not be completed until the underlying socket is
     * ready for writing more data. When NEED_WRITE is returned,
     * either write or flush will be called again when the appropriate
     * io event has triggered.
     **/
    public FlushResult flush() throws IOException;

    /**
     * This function can be called at any time to drop any currently
     * empty internal buffers. Typically called after drain or flush
     * indicates that no further progress can be made.
     **/
    public void dropEmptyBuffers();

    /**
     * Returns the security context for the current connection (given handshake completed),
     * or empty if the current connection is not secure.
     */
    default public Optional<SecurityContext> getSecurityContext() {
        return Optional.empty();
    }
}