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 
16 
17 import std.socket;
18 import std.exception;
19 import hunt.logging;
20 
21 /**
22 */
23 class UdpSocket : AbstractDatagramSocket
24 {
25 
26     this(EventLoop loop, AddressFamily amily = AddressFamily.INET)
27     {
28         super(loop, amily);
29     }
30 
31     UdpSocket setReadData(UDPReadCallBack cback)
32     {
33         _readBack = cback;
34         return this;
35     }
36 
37     ptrdiff_t sendTo(const(void)[] buf, Address to)
38     {
39         return this.socket.sendTo(buf, to);
40     }
41 
42     ptrdiff_t sendTo(const(void)[] buf)
43     {
44         return this.socket.sendTo(buf);
45     }
46 
47     ptrdiff_t sendTo(const(void)[] buf, SocketFlags flags, Address to)
48     {
49         return this.socket.sendTo(buf, flags, to);
50     }
51 
52     UdpSocket bind(string ip, ushort port)
53     {
54         super.bind(parseAddress(ip, port));
55         return this;
56     }
57 
58     UdpSocket connect(Address addr)
59     {
60         this.socket.connect(addr);
61         return this;
62     }
63 
64     override void start()
65     {
66         if (!_binded)
67         {
68             socket.bind(_bindAddress);
69             _binded = true;
70         }
71 
72         _inLoop.register(this);
73         _isRegistered = true;
74         version (HAVE_IOCP)
75             doRead();
76     }
77 
78 protected:
79     override void onRead() nothrow
80     {
81         catchAndLogException(() {
82             bool canRead = true;
83             while (canRead && _isRegistered)
84             {
85                 version (HUNT_DEBUG)
86                     trace("reading data...");
87                 canRead = tryRead((Object obj) nothrow{
88                     collectException(() {
89                         UdpDataObject data = cast(UdpDataObject) obj;
90                         if (data !is null)
91                         {
92                             _readBack(data.data, data.addr);
93                         }
94                     }());
95                 });
96 
97                 if (this.isError)
98                 {
99                     canRead = false;
100                     this.close();
101                     error("UDP socket error: ", this.erroString);
102                 }
103             }
104         }());
105     }
106 
107 private:
108     UDPReadCallBack _readBack;
109 }