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