1 /*
2  * Hunt - A refined core library for D programming language.
3  *
4  * Copyright (C) 2018-2019 HuntLabs
5  *
6  * Website: https://www.huntlabs.net/
7  *
8  * Licensed under the Apache-2.0 License.
9  *
10  */
11 
12 module hunt.io.UdpSocket;
13 
14 import hunt.event;
15 import hunt.logging;
16 
17 import std.socket;
18 import std.exception;
19 
20 /**
21 */
22 class UdpSocket : AbstractDatagramSocket {
23 
24     private UdpDataHandler _receivedHandler;
25 
26     this(EventLoop loop, AddressFamily amily = AddressFamily.INET) {
27         super(loop, amily);
28     }
29     
30     UdpSocket enableBroadcast(bool flag) {
31         this.socket.setOption(SocketOptionLevel.SOCKET, SocketOption.BROADCAST, flag);
32         return this;
33     }
34 
35     UdpSocket onReceived(UdpDataHandler handler) {
36         _receivedHandler = handler;
37         return this;
38     }
39 
40     ptrdiff_t sendTo(const(void)[] buf, Address to) {
41         return this.socket.sendTo(buf, to);
42     }
43 
44     ptrdiff_t sendTo(const(void)[] buf) {
45         return this.socket.sendTo(buf);
46     }
47 
48     ptrdiff_t sendTo(const(void)[] buf, SocketFlags flags, Address to) {
49         return this.socket.sendTo(buf, flags, to);
50     }
51 
52     UdpSocket bind(string ip, ushort port) {
53         super.bind(parseAddress(ip, port));
54         return this;
55     }
56 
57     UdpSocket bind(Address address) {
58         super.bind(address);
59         return this;
60     }
61 
62     UdpSocket connect(Address addr) {
63         this.socket.connect(addr);
64         return this;
65     }
66 
67     override void start() {
68         if (!_binded) {
69             socket.bind(_bindAddress);
70             _binded = true;
71         }
72 
73         _inLoop.register(this);
74         _isRegistered = true;
75         version (HAVE_IOCP)
76             doRead();
77     }
78 
79     protected override void onRead() nothrow {
80         catchAndLogException(() {
81             bool canRead = true;
82             while (canRead && _isRegistered) {
83                 version (HUNT_IO_DEBUG)
84                     trace("reading data...");
85                 canRead = tryRead((Object obj) nothrow{
86                     collectException(() {
87                         UdpDataObject data = cast(UdpDataObject) obj;
88                         if (data !is null) {
89                             _receivedHandler(data.data, data.addr);
90                         }
91                     }());
92                 });
93 
94                 if (this.isError) {
95                     canRead = false;
96                     this.close();
97                     error("UDP socket error: ", this.errorMessage);
98                 }
99             }
100         }());
101     }
102 
103 }