ReceivePacketMiddleware
last analyzed

Complexity

Total Complexity 0

Size/Duplication

Total Lines 9
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 9
ccs 0
cts 0
cp 0
wmc 0

1 Method

Rating   Name   Duplication   Size   Complexity  
handlePacket(Object,Consumer) 0 1 ?
1
/*
2
 * This file is part of Araknemu.
3
 *
4
 * Araknemu is free software: you can redistribute it and/or modify
5
 * it under the terms of the GNU Lesser General Public License as published by
6
 * the Free Software Foundation, either version 3 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * Araknemu is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU Lesser General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU Lesser General Public License
15
 * along with Araknemu.  If not, see <https://www.gnu.org/licenses/>.
16
 *
17
 * Copyright (c) 2017-2019 Vincent Quatrevieux
18
 */
19
20
package fr.quatrevieux.araknemu.core.network.session;
21
22
import fr.quatrevieux.araknemu.core.network.Channel;
23
import fr.quatrevieux.araknemu.core.network.InternalPacket;
24
25
import java.util.ArrayList;
26
import java.util.List;
27
import java.util.function.Consumer;
28
import java.util.function.Predicate;
29
30
/**
31
 * Simple session implementation with configurable handlers for each methods
32
 */
33
public final class ConfigurableSession implements Session {
34
    private final Channel channel;
35
36 1
    private final List<SendPacketTransformer> sendTransformers = new ArrayList<>();
37 1
    private final List<ReceivePacketMiddleware> receiveMiddlewares = new ArrayList<>();
38 1
    private final List<ExceptionHandler> exceptionHandlers = new ArrayList<>();
39
40 1
    public ConfigurableSession(Channel channel) {
41 1
        this.channel = channel;
42 1
    }
43
44
    @Override
45
    public Channel channel() {
46 1
        return channel;
47
    }
48
49
    @Override
50
    public void send(Object packet) {
51 1
        if (!isAlive()) {
52 1
            return;
53
        }
54
55 1
        for (SendPacketTransformer transformer : sendTransformers) {
56 1
            if ((packet = transformer.transformPacket(packet)) == null) {
57 1
                return;
58
            }
59 1
        }
60
61 1
        channel.write(packet);
62 1
    }
63
64
    @Override
65
    public void receive(Object packet) {
66
        // Do not handle received packet if the session is closed
67
        // But handle internal packets (like SessionClosed)
68 1
        if (!(packet instanceof InternalPacket) && !isAlive()) {
69 1
            return;
70
        }
71
72 1
        final Consumer<Object> next = new Consumer<Object>() {
73 1
            private int index = 0;
74
75
            @Override
76
            public void accept(Object o) {
77
                try {
78 1
                    receiveMiddlewares.get(index++).handlePacket(o, this);
79 1
                } catch (Exception e) {
80 1
                    exception(e);
81 1
                }
82 1
            }
83
        };
84
85 1
        next.accept(packet);
86 1
    }
87
88
    @Override
89
    @SuppressWarnings("unchecked")
90
    public void exception(Throwable cause) {
91 1
        boolean handled = false;
92
93 1
        for (ExceptionHandler handler : exceptionHandlers) {
94 1
            if (handler.type().isInstance(cause)) {
95 1
                handled = true;
96
97 1
                if (!handler.handleException(cause)) {
98 1
                    break;
99
                }
100
            }
101 1
        }
102
103 1
        if (!handled) {
104 1
            throw new IllegalArgumentException("Unhandled exception", cause);
105
        }
106 1
    }
107
108
    @Override
109
    public void close() {
110 1
        channel.close();
111 1
    }
112
113
    @Override
114
    public boolean isAlive() {
115 1
        return channel.isAlive();
116
    }
117
118
    /**
119
     * Add a transformer for sending packets
120
     * All the transformers are called before write into the channel
121
     * If a transformer return null, the packet will be not sent
122
     */
123
    public void addSendTransformer(SendPacketTransformer transformer) {
124 1
        sendTransformers.add(transformer);
125 1
    }
126
127
    /**
128
     * Add a middleware for and received packets
129
     * The last added middleware will be the last executed (endpoint)
130
     *
131
     * <code>
132
     *     session.addReceiveMiddleware((packet, next) -> {
133
     *         before(packet);
134
     *
135
     *         next.accept(transformPacket(packet));
136
     *
137
     *         after(packet);
138
     *     })
139
     * </code>
140
     */
141
    public void addReceiveMiddleware(ReceivePacketMiddleware middleware) {
142 1
        receiveMiddlewares.add(middleware);
143 1
    }
144
145
    /**
146
     * Add a new exception handler at the end of the list
147
     */
148
    public void addExceptionHandler(ExceptionHandler handler) {
149 1
        exceptionHandlers.add(handler);
150 1
    }
151
152
    /**
153
     * Add a simple exception handler
154
     *
155
     * @param type The handled exception class
156
     * @param handle The exception handler
157
     *
158
     * @param <E> The exception type
159
     */
160
    public <E> void addExceptionHandler(Class<E> type, Predicate<E> handle) {
161 1
        addExceptionHandler(new ExceptionHandler() {
162
            @Override
163
            public Class<E> type() {
164 1
                return type;
165
            }
166
167
            @Override
168
            @SuppressWarnings("unchecked")
169
            public boolean handleException(Throwable cause) {
170 1
                return handle.test((E) cause);
171
            }
172
        });
173 1
    }
174
175
    /**
176
     * Handle exceptions thrown during a session
177
     *
178
     * @param <E> The exception type
179
     */
180
    public interface ExceptionHandler<E extends Throwable> {
181
        /**
182
         * The supported exception type
183
         */
184
        public Class<E> type();
185
186
        /**
187
         * Handle the exception
188
         *
189
         * @return true for call next handlers, or false to stop exception handling
190
         */
191
        public boolean handleException(E cause);
192
    }
193
194
    /**
195
     * Middleware for handle received packets
196
     */
197
    @FunctionalInterface
198
    public interface ReceivePacketMiddleware {
199
        /**
200
         * Handle a packet
201
         *
202
         * @param packet Packet to handle
203
         * @param next The next middleware to call
204
         */
205
        public void handlePacket(Object packet, Consumer<Object> next) throws Exception;
206
    }
207
208
    /**
209
     * Transform packets before sending
210
     */
211
    @FunctionalInterface
212
    public interface SendPacketTransformer {
213
        /**
214
         * Transform the packet
215
         *
216
         * @param packet Original packet
217
         *
218
         * @return The transformed packet, or null to cancel sending
219
         */
220
        public Object transformPacket(Object packet);
221
    }
222
}
223