1 module osc.server; 2 3 import std.socket; 4 import core.thread; 5 import core.sync.mutex; 6 7 import osc.message; 8 import osc.bundle; 9 import osc.packet; 10 11 12 13 /// A server receiving OSC packets. 14 /// 15 class OSCServer 16 { 17 18 private { 19 Socket _listener; 20 OSCMessage[] _buffer; 21 22 Mutex _bufferLock; 23 Thread _thread; 24 25 bool _running; 26 } 27 28 29 30 /// Constructs a new server using an already created socket. 31 /// 32 this( Socket sock ) 33 { 34 _listener = sock; 35 _bufferLock = new Mutex( ); 36 37 _listener.setOption( SocketOptionLevel.SOCKET, SocketOption.RCVTIMEO, dur!"seconds"( 1 ) ); 38 } 39 40 /// Constructs a new server using an UDP socket for IPv4 addresses. 41 /// 42 this( ) 43 { 44 this( new Socket( AddressFamily.INET, SocketType.DGRAM ) ); 45 } 46 47 48 49 /// Binds the server to the given address. 50 /// 51 void bind( Address addr ) 52 in 53 { 54 assert( _thread is null ); 55 } 56 do 57 { 58 _listener.bind( addr ); 59 _thread = new Thread( () => _receive() ).start; 60 } 61 62 /// Binds the server to the given IPv4 IP and port. 63 /// 64 void bind( string ip, ushort port ) 65 in 66 { 67 assert( _thread is null ); 68 } 69 do 70 { 71 _listener.bind( new InternetAddress( ip, port ) ); 72 _thread = new Thread( () => _receive() ).start; 73 } 74 75 /// Binds the server to the "localhost" IP using the given local port. 76 /// 77 void bind( ushort port ) 78 in 79 { 80 assert( _thread is null ); 81 } 82 do 83 { 84 _listener.bind( new InternetAddress( "localhost", port ) ); 85 _thread = new Thread( () => _receive() ).start; 86 } 87 88 89 90 /// Closes the server. 91 /// 92 void close( ) 93 { 94 _running = false; 95 96 _listener.close; 97 _thread.join; 98 } 99 100 101 102 /// Gets the next message received. 103 /// 104 OSCMessage pop( ) 105 { 106 if( _buffer.length == 0 ) 107 return null; 108 109 _bufferLock.lock; 110 scope( exit ) 111 _bufferLock.unlock; 112 113 OSCMessage msg = _buffer[ 0 ]; 114 _buffer = _buffer[ 1 .. $ ]; 115 116 return msg; 117 118 } 119 120 /// Checks if some messages are in the server buffer. 121 /// 122 bool empty( ) 123 { 124 return _buffer.length == 0; 125 } 126 127 128 129 130 private void _receive( ) { 131 ubyte[16_192] buffer; 132 133 _running = true; 134 135 while( _running ) { 136 137 ptrdiff_t size = _listener.receive( buffer ); 138 139 if( size <= 0 ) 140 continue; 141 142 OSCMessage[] received; 143 OSCPacket p = OSCPacket.parse( buffer[ 0 .. size ] ); 144 145 if( cast(OSCBundle) p !is null ) 146 received = ( cast(OSCBundle) p ).messages; 147 else 148 received ~= cast(OSCMessage)p; 149 150 _bufferLock.lock; 151 foreach( m; received ) 152 _buffer ~= m; 153 _bufferLock.unlock; 154 } 155 } 156 157 }