1 module hunt.io.channel.iocp.AbstractDatagramSocket;
2 
3 // dfmt off
4 version (HAVE_IOCP) : 
5 // dfmt on
6 
7 // import hunt.io.ByteBuffer;
8 // import hunt.io.BufferUtils;
9 import hunt.event.selector.Selector;
10 import hunt.io.channel.AbstractSocketChannel;
11 import hunt.io.channel.Common;
12 import hunt.io.channel.iocp.Common;
13 import hunt.logging.ConsoleLogger;
14 import hunt.Functions;
15 
16 // import hunt.util.ThreadHelper;
17 
18 // import core.atomic;
19 import core.sys.windows.windows;
20 import core.sys.windows.winsock2;
21 import core.sys.windows.mswsock;
22 
23 // import std.conv;
24 // import std.exception;
25 // import std.format;
26 // import std.process;
27 import std.socket;
28 
29 // import std.stdio;
30 
31 /**
32 UDP Socket
33 */
34 abstract class AbstractDatagramSocket : AbstractSocketChannel {
35     /// Constructs a blocking IPv4 UDP Socket.
36     this(Selector loop, AddressFamily family = AddressFamily.INET) {
37         super(loop, ChannelType.UDP);
38         setFlag(ChannelFlag.Read, true);
39         // setFlag(ChannelFlag.ETMode, false);
40 
41         this.socket = new UdpSocket(family);
42         _readBuffer = new UdpDataObject();
43         _readBuffer.data = new ubyte[4096 * 2];
44 
45         if (family == AddressFamily.INET)
46             _bindAddress = new InternetAddress(InternetAddress.PORT_ANY);
47         else if (family == AddressFamily.INET6)
48             _bindAddress = new Internet6Address(Internet6Address.PORT_ANY);
49         else
50             _bindAddress = new UnknownAddress();
51     }
52 
53     final void bind(Address addr) {
54         if (_binded)
55             return;
56         _bindAddress = addr;
57         socket.bind(_bindAddress);
58         _binded = true;
59     }
60 
61     final bool isBind() {
62         return _binded;
63     }
64 
65     Address bindAddr() {
66         return _bindAddress;
67     }
68 
69     override void start() {
70         if (!_binded) {
71             socket.bind(_bindAddress);
72             _binded = true;
73         }
74     }
75 
76     // abstract void doRead();
77 
78     private UdpDataObject _readBuffer;
79     protected bool _binded = false;
80     protected Address _bindAddress;
81 
82     mixin CheckIocpError;
83 
84     void doRead() {
85         version (HUNT_IO_DEBUG)
86             trace("Receiving......");
87 
88         _dataReadBuffer.len = cast(uint) _readBuffer.data.length;
89         _dataReadBuffer.buf = cast(char*) _readBuffer.data.ptr;
90         _iocpread.channel = this;
91         _iocpread.operation = IocpOperation.read;
92         remoteAddrLen = cast(int) bindAddr().nameLen();
93 
94         DWORD dwReceived = 0;
95         DWORD dwFlags = 0;
96 
97         int nRet = WSARecvFrom(cast(SOCKET) this.handle, &_dataReadBuffer,
98                 cast(uint) 1, &dwReceived, &dwFlags, cast(SOCKADDR*)&remoteAddr, &remoteAddrLen,
99                 &_iocpread.overlapped, cast(LPWSAOVERLAPPED_COMPLETION_ROUTINE) null);
100         checkErro(nRet, SOCKET_ERROR);
101     }
102 
103     Address buildAddress() {
104         Address tmpaddr;
105         if (remoteAddrLen == 32) {
106             sockaddr_in* addr = cast(sockaddr_in*)(&remoteAddr);
107             tmpaddr = new InternetAddress(*addr);
108         } else {
109             sockaddr_in6* addr = cast(sockaddr_in6*)(&remoteAddr);
110             tmpaddr = new Internet6Address(*addr);
111         }
112         return tmpaddr;
113     }
114 
115     bool tryRead(scope SimpleActionHandler read) {
116         this.clearError();
117         if (this.readLen == 0) {
118             read(null);
119         } else {
120             ubyte[] data = this._readBuffer.data;
121             this._readBuffer.data = data[0 .. this.readLen];
122             this._readBuffer.addr = this.buildAddress();
123             scope (exit)
124                 this._readBuffer.data = data;
125             read(this._readBuffer);
126             this._readBuffer.data = data;
127             if (this.isRegistered)
128                 this.doRead();
129         }
130         return false;
131     }
132 
133     IocpContext _iocpread;
134     WSABUF _dataReadBuffer;
135 
136     sockaddr remoteAddr;
137     int remoteAddrLen;
138 
139 }