1 /* 2 DSFML - The Simple and Fast Multimedia Library for D 3 4 Copyright (c) 2013 - 2015 Jeremy DeHaan (dehaan.jeremiah@gmail.com) 5 6 This software is provided 'as-is', without any express or implied warranty. 7 In no event will the authors be held liable for any damages arising from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, including commercial applications, 10 and to alter it and redistribute it freely, subject to the following restrictions: 11 12 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. 13 If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 14 15 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 16 17 3. This notice may not be removed or altered from any source distribution 18 */ 19 20 ///A module containing the TcpListener class. 21 module dsfml.network.tcplistener; 22 23 24 import dsfml.network.socket; 25 import dsfml.network.tcpsocket; 26 27 import dsfml.system.err; 28 29 /** 30 *Socket that listens to new TCP connections. 31 * 32 *A listener socket is a special type of socket that listens to a given port and waits for connections on that port. 33 * 34 *This is all it can do. 35 * 36 *When a new connection is received, you must call accept and the listener returns a new instance of sf::TcpSocket that is properly initialized and can be used to communicate with the new client. 37 * 38 *Listener sockets are specific to the TCP protocol, UDP sockets are connectionless and can therefore communicate directly. As a consequence, a listener socket will always return the new connections as sf::TcpSocket instances. 39 * 40 *A listener is automatically closed on destruction, like all other types of socket. However if you want to stop listening before the socket is destroyed, you can call its close() function. 41 */ 42 class TcpListener:Socket 43 { 44 package sfTcpListener* sfPtr; 45 46 ///Default constructor 47 this() 48 { 49 sfPtr = sfTcpListener_create(); 50 } 51 52 ///Destructor 53 ~this() 54 { 55 import dsfml.system.config; 56 mixin(destructorOutput); 57 sfTcpListener_destroy(sfPtr); 58 } 59 60 ///Get the port to which the socket is bound locally. 61 /// 62 ///If the socket is not listening to a port, this function returns 0. 63 /// 64 ///Returns: Port to which the socket is bound. 65 ushort getLocalPort() 66 { 67 return sfTcpListener_getLocalPort(sfPtr); 68 } 69 70 ///Tell whether the socket is in blocking or non-blocking mode. 71 /// 72 ///In blocking mode, calls will not return until they have completed their task. For example, a call to Receive in blocking mode won't return until some data was actually received. In non-blocking mode, calls will always return immediately, using the return code to signal whether there was data available or not. By default, all sockets are blocking. 73 /// 74 ///Params: 75 /// blocking = True to set the socket as blocking, false for non-blocking. 76 void setBlocking(bool blocking) 77 { 78 sfTcpListener_setBlocking(sfPtr, blocking); 79 } 80 81 ///Accept a new connection. 82 // 83 ///If the socket is in blocking mode, this function will not return until a connection is actually received. 84 /// 85 ///Params: 86 /// socket = Socket that will hold the new connection. 87 /// 88 ///Returns: Status code. 89 Status accept(TcpSocket socket) 90 { 91 import dsfml.system..string; 92 93 Status toReturn = sfTcpListener_accept(sfPtr, socket.sfPtr); 94 err.write(dsfml.system..string.toString(sfErr_getOutput())); 95 return toReturn; 96 } 97 98 ///Start listening for connections. 99 /// 100 ///This functions makes the socket listen to the specified port, waiting for new connections. If the socket was previously listening to another port, it will be stopped first and bound to the new port. 101 /// 102 ///Params: 103 /// port = Port to listen for new connections. 104 /// 105 ///Returns: Status code. 106 Status listen(ushort port) 107 { 108 import dsfml.system..string; 109 110 Status toReturn = sfTcpListener_listen(sfPtr, port); 111 err.write(dsfml.system..string.toString(sfErr_getOutput())); 112 return toReturn; 113 } 114 115 ///Set the blocking state of the socket. 116 /// 117 ///In blocking mode, calls will not return until they have completed their task. For example, a call to Receive in blocking mode won't return until some data was actually received. In non-blocking mode, calls will always return immediately, using the return code to signal whether there was data available or not. By default, all sockets are blocking. 118 /// 119 ///Returns: True if the socket is blocking, false otherwise. 120 bool isBlocking() 121 { 122 return (sfTcpListener_isBlocking(sfPtr)); 123 } 124 125 } 126 127 unittest 128 { 129 version(DSFML_Unittest_Network) 130 { 131 import std.stdio; 132 import dsfml.network.ipaddress; 133 134 writeln("Unittest for Listener"); 135 //socket connecting to server 136 auto clientSocket = new TcpSocket(); 137 138 //listener looking for new sockets 139 auto listener = new TcpListener(); 140 listener.listen(55002); 141 142 writeln("The listener is listening to port ", listener.getLocalPort()); 143 144 //get our client socket to connect to the server 145 clientSocket.connect(IpAddress.LocalHost, 55002); 146 147 148 //socket on the server side connected to the client's socket 149 auto serverSocket = new TcpSocket(); 150 151 //accepts a new connection and binds it to the socket in the parameter 152 listener.accept(serverSocket); 153 154 155 clientSocket.disconnect(); 156 writeln(); 157 } 158 } 159 160 package extern(C): 161 162 struct sfTcpListener; 163 164 sfTcpListener* sfTcpListener_create(); 165 166 167 //Destroy a TCP listener 168 void sfTcpListener_destroy(sfTcpListener* listener); 169 170 171 //Set the blocking state of a TCP listener 172 void sfTcpListener_setBlocking(sfTcpListener* listener, bool blocking); 173 174 175 //Tell whether a TCP listener is in blocking or non-blocking mode 176 bool sfTcpListener_isBlocking(const sfTcpListener* listener); 177 178 179 //Get the port to which a TCP listener is bound locally 180 ushort sfTcpListener_getLocalPort(const(sfTcpListener)* listener); 181 182 183 //Start listening for connections 184 Socket.Status sfTcpListener_listen(sfTcpListener* listener, ushort port); 185 186 187 //Accept a new connection 188 Socket.Status sfTcpListener_accept(sfTcpListener* listener, sfTcpSocket* connected); 189 190 const(char)* sfErr_getOutput();