1 /******************************************************************************* 2 3 Sample unix socket server, which is based on fiber select listener. 4 5 Copyright: 6 Copyright (c) 2016-2017 dunnhumby Germany GmbH. 7 All rights reserved. 8 9 License: 10 Boost Software License Version 1.0. See LICENSE_BOOST.txt for details. 11 Alternatively, this file may be distributed under the terms of the Tango 12 3-Clause BSD License (see LICENSE_BSD.txt for details). 13 14 *******************************************************************************/ 15 16 module integrationtest.selectlistener.UnixServer; 17 18 import ocean.io.select.EpollSelectDispatcher; 19 import ocean.io.select.protocol.fiber.FiberSelectReader; 20 import ocean.io.select.protocol.fiber.FiberSelectWriter; 21 import ocean.io.select.protocol.generic.ErrnoIOException : SocketError; 22 import ocean.net.server.SelectListener; 23 import ocean.net.server.connection.IFiberConnectionHandler; 24 import ocean.sys.socket.UnixSocket; 25 26 27 /******************************************************************************* 28 29 The server is based on SelectListener. 30 31 *******************************************************************************/ 32 33 public alias SelectListener!(UnixConnectionHandler, EpollSelectDispatcher) UnixServer; 34 35 36 /******************************************************************************* 37 38 The connection handler is based on IFiberConnectionHandler 39 40 *******************************************************************************/ 41 42 private class UnixConnectionHandler: IFiberConnectionHandler 43 { 44 /*************************************************************************** 45 46 Keeps data between `consume` calls. 47 48 ***************************************************************************/ 49 50 char[] buffer; 51 52 53 /*************************************************************************** 54 55 Shuts down the server when one request is served. 56 57 ***************************************************************************/ 58 59 EpollSelectDispatcher epoll; 60 61 62 /*************************************************************************** 63 64 Consumer callback delegate type 65 66 Params: 67 data = data to consume 68 69 Returns: 70 - if finished, a value of [0, data.length] reflecting the number of 71 elements (bytes) consumed or 72 - a value greater than data.length if more data is required. 73 74 ***************************************************************************/ 75 76 private size_t consume( void[] data ) 77 { 78 char[] input = cast(char[])data; 79 size_t n = 0; 80 81 foreach ( size_t i, char c; input ) 82 { 83 n++; 84 if ( c == '\n' ) 85 { 86 return n; 87 } 88 buffer ~= c; 89 } 90 91 // If we need more data, we must return a value greater than data.length. 92 return data.length + 1; 93 } 94 95 96 /*************************************************************************** 97 98 Constructor 99 100 ***************************************************************************/ 101 102 public this ( scope FinalizeDg finalize_dg, EpollSelectDispatcher epoll ) 103 { 104 super(epoll, new UnixSocket, finalize_dg); 105 106 this.epoll = epoll; 107 } 108 109 110 /*************************************************************************** 111 112 Connection handler method. If it catches exceptions, it must rethrow 113 those of type KilledException. 114 115 ***************************************************************************/ 116 117 protected override void handle ( ) 118 { 119 auto exception = new SocketError(this.socket); 120 121 FiberSelectReader reader = new FiberSelectReader(this.socket, 122 this.fiber, exception, exception); 123 this.reader.error_reporter = this; 124 125 FiberSelectWriter writer = new FiberSelectWriter(this.socket, 126 this.fiber, exception, exception); 127 this.reader.error_reporter = this; 128 129 scope(exit) 130 { 131 this.epoll.shutdown(); 132 // Is anything else needed? 133 } 134 135 // In production code, this may be to be wrapped in a `while`. 136 buffer.length = 0; 137 reader.readConsume(&this.consume); 138 buffer ~= "\n"; 139 writer.send(buffer); 140 } 141 }