1 /*******************************************************************************
2 
3         copyright:      Copyright (c) 2004 Kris Bell. All rights reserved
4 
5         license:        BSD style: $(LICENSE)
6 
7         version:        Mar 2004 : Initial release
8         version:        Dec 2006 : South Pacific release
9         
10         author:         Kris
11 
12 *******************************************************************************/
13 
14 module tango.net.device.Datagram;
15 
16 private import tango.net.device.Socket;
17 private import tango.net.device.Berkeley;
18 
19 /*******************************************************************************
20         
21         Datagrams provide a low-overhead, non-reliable data transmission
22         mechanism.
23 
24         Datagrams are not 'connected' in the same manner as a TCP socket; you
25         don't need to listen() or accept() to receive a datagram, and data
26         may arrive from multiple sources. A datagram socket may, however,
27         still use the connect() method like a TCP socket. When connected,
28         the read() and write() methods will be restricted to a single address
29         rather than being open instead. That is, applying connect() will make
30         the address argument to both read() and write() irrelevant. Without
31         connect(), method write() must be supplied with an address and method
32         read() should be supplied with one to identify where data originated.
33         
34         Note that when used as a listener, you must first bind the socket
35         to a local adapter. This can be achieved by binding the socket to
36         an InternetAddress constructed with a port only (ADDR_ANY), thus
37         requesting the OS to assign the address of a local network adapter
38 
39 *******************************************************************************/
40 
41 class Datagram : Socket
42 {
43         /***********************************************************************
44         
45                 Create a read/write datagram socket
46 
47         ***********************************************************************/
48 
49         this ()
50         {
51                 super (AddressFamily.INET, SocketType.DGRAM, ProtocolType.IP);
52         }
53 
54         /***********************************************************************
55 
56                 Populate the provided array from the socket. This will stall
57                 until some data is available, or a timeout occurs. We assume 
58                 the datagram has been connected.
59 
60                 Returns the number of bytes read to the output, or Eof if
61                 the socket cannot read
62 
63         ***********************************************************************/
64 
65         override size_t read (void[] src)
66         {
67                 return read (src, null);
68         }
69 
70         /***********************************************************************
71         
72                 Read bytes from an available datagram into the given array.
73                 When provided, the 'from' address will be populated with the
74                 origin of the incoming data. Note that we employ the timeout
75                 mechanics exposed via our Socket superclass. 
76 
77                 Returns the number of bytes read from the input, or Eof if
78                 the socket cannot read
79 
80         ***********************************************************************/
81 
82         size_t read (void[] dst, Address from)
83         {
84                 size_t count;
85 
86                 if (dst.length)
87                    {
88                    count = (from ? native.receiveFrom(dst, from) : native.receiveFrom(dst));
89                    if (count <= 0)
90                        count = Eof;
91                    }
92 
93                 return count;
94         }
95 
96         /***********************************************************************
97 
98                 Write the provided content to the socket. This will stall
99                 until the socket responds in some manner. We assume the 
100                 datagram has been connected.
101 
102                 Returns the number of bytes sent to the output, or Eof if
103                 the socket cannot write
104 
105         ***********************************************************************/
106 
107         override size_t write (const(void)[] src)
108         {
109                 return write (src, null);
110         }
111 
112         /***********************************************************************
113         
114                 Write an array to the specified address. If address 'to' is
115                 null, it is assumed the socket has been connected instead.
116 
117                 Returns the number of bytes sent to the output, or Eof if
118                 the socket cannot write
119 
120         ***********************************************************************/
121 
122         size_t write (const(void)[] src, Address to)
123         {
124                 int count = Eof;
125                 
126                 if (src.length)
127                    {
128                    count = (to) ? native.sendTo(src, to) : native.sendTo(src);
129                    if (count <= 0)
130                        count = Eof;
131                    }
132                 return count;
133         }
134 }
135 
136 
137 
138 /******************************************************************************
139 
140 *******************************************************************************/
141 
142 debug (Datagram)
143 {
144         import tango.io.Console;
145 
146         import tango.net.InternetAddress;
147 
148         void main()
149         {
150                 auto addr = new InternetAddress ("127.0.0.1", 8080);
151 
152                 // listen for datagrams on the local address
153                 auto gram = new Datagram;
154                 gram.bind (addr);
155 
156                 // write to the local address
157                 gram.write ("hello", addr);
158 
159                 // we are listening also ...
160                 char[8] tmp;
161                 auto x = new InternetAddress;
162                 auto bytes = gram.read (tmp, x);
163                 Cout (x) (tmp[0..bytes]).newline;
164         }
165 }