FreeNOS
UDP.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2015 Niek Linnenbank
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <ByteOrder.h>
19#include "NetworkServer.h"
20#include "NetworkDevice.h"
21#include "UDP.h"
22#include "UDPSocket.h"
23#include "UDPFactory.h"
24
26 NetworkDevice &device,
27 NetworkProtocol &parent)
28 : NetworkProtocol(server, device, parent)
29{
30}
31
33{
34}
35
37{
38 DEBUG("");
39
41 m_server.registerDirectory(this, "/udp");
42 m_server.registerFile(m_factory, "/udp/factory");
43
45}
46
48 const ProcessID pid)
49{
50 Size pos = 0;
51
52 DEBUG("");
53
54 UDPSocket *sock = new UDPSocket(m_server.getNextInode(), this, pid);
55 if (!sock)
56 {
57 ERROR("failed to allocate UDP socket");
58 return ZERO;
59 }
60
61 if (!m_sockets.insert(pos, sock))
62 {
63 ERROR("failed to insert UDP socket");
64 delete sock;
65 return ZERO;
66 }
67 String filepath;
68 filepath << "/udp/" << pos;
69
70 path << m_server.getMountPath() << filepath;
71 const FileSystem::Result result = m_server.registerFile(sock, *filepath);
72 if (result != FileSystem::Success)
73 {
74 ERROR("failed to register UDP socket: result = " << (int) result);
75 delete sock;
76 m_sockets.remove(pos);
77 }
78
79 return sock;
80}
81
83{
84 DEBUG("pid = " << pid);
85
87 {
88 UDPSocket *sock = it.current();
89 if (sock->getProcessID() == pid)
90 {
91 it.remove();
92 }
93 else
94 {
95 it++;
96 }
97 }
98
99 for (Size i = 0; i < MaxUdpSockets; i++)
100 {
101 UDPSocket *sock = m_sockets[i];
102 if (sock != ZERO && sock->getProcessID() == pid)
103 {
104 m_sockets.remove(i);
105 String path;
106 path << "/udp/" << i;
107 const FileSystem::Result result = m_server.unregisterFile(*path);
108 if (result != FileSystem::Success)
109 {
110 ERROR("failed to unregister UDPSocket at " << *path <<
111 " for PID " << pid << ": result = " << (int) result);
112 }
113 }
114 }
115}
116
118 const Size offset)
119{
120 const Header *hdr = (const Header *)(pkt->data + sizeof(Ethernet::Header) + sizeof(IPV4::Header));
121 const u16 port = be16_to_cpu(hdr->destPort);
122
123 DEBUG("port = " << port);
124
125 // Process the packet if we have a socket on that port
126 UDPSocket **sock = (UDPSocket **) m_ports.get(port);
127 if (!sock)
128 {
129 DEBUG("dropped");
131 }
132
133 (*sock)->process(pkt);
134 return FileSystem::Success;
135}
136
138 const NetworkClient::SocketInfo *dest,
139 IOBuffer & buffer,
140 const Size size,
141 const Size offset)
142{
144 Header *hdr;
145
146 DEBUG("address = " << *IPV4::toString(dest->address) <<
147 " port = " << dest->port << " size = " << size);
148
149 // Get a fresh packet
150 const FileSystem::Result result = m_parent.getTransmitPacket(&pkt, &dest->address, sizeof(dest->address),
151 NetworkProtocol::UDP, sizeof(Header) + size);
152 if (result != FileSystem::Success)
153 {
154 if (result != FileSystem::RetryAgain)
155 {
156 ERROR("failed to get transmit packet: result = " << (int) result);
157 }
158 return result;
159 }
160
161 // Fill UDP header
162 hdr = (Header *) (pkt->data + pkt->size);
163 writeBe16(&hdr->sourcePort, src->port);
164 writeBe16(&hdr->destPort, dest->port);
165 writeBe16(&hdr->length, size + sizeof(Header));
166 writeBe16(&hdr->checksum, 0);
167
168 // Insert payload. The payload is read from the given offset in the IOBuffer.
169 // Note that the payload must not overwrite past the packet buffer
170 const Size maximum = getMaximumPacketSize();
171 const Size needed = pkt->size + size;
172
173 buffer.read(pkt->data + pkt->size + sizeof(Header),
174 needed > maximum ? maximum : needed, offset);
175
176 // Calculate final checksum
177 write16(&hdr->checksum, checksum((IPV4::Header *)(pkt->data + pkt->size - sizeof(IPV4::Header)),
178 hdr, size));
179 DEBUG("checksum = " << (uint) hdr->checksum);
180
181 // Increment packet size
182 pkt->size += sizeof(Header) + size;
183
184 // Transmit now
185 return m_device.transmit(pkt);
186}
187
189 const u16 port)
190{
191 DEBUG("port = " << port);
192
193 if (!port)
194 {
196 }
197
198 m_ports.insert(port, sock);
199 return FileSystem::Success;
200}
201
202const ulong UDP::calculateSum(const u16 *ptr,
203 const Size bytes)
204{
205 ulong sum = 0;
206 Size remain = bytes;
207
208 for (;remain > 0; remain -= sizeof(u16), ptr++)
209 {
210 if (remain == sizeof(u8))
211 {
212 sum += read8(ptr);
213 break;
214 }
215 else
216 {
217 sum += read16(ptr);
218 }
219 }
220
221 return sum;
222}
223
225 const UDP::Header *udp,
226 const Size datalen)
227{
229 ulong sum = 0;
230
231 // Setup a pseudo header
232 phr.reserved = 0;
233 phr.protocol = IPV4::UDP;
234 phr.source = read32(&ip->source);
235 phr.destination = read32(&ip->destination);
236 writeBe16(&phr.length, sizeof(Header) + datalen);
237 DEBUG("ip src = " << *IPV4::toString(phr.source) <<
238 " dst = " << *IPV4::toString(phr.destination));
239
240 // Sum the pseudo header
241 sum += calculateSum((u16 *) &phr, sizeof(phr));
242 sum += calculateSum((u16 *) udp, sizeof(*udp) + datalen);
243
244 // Keep only last 16 bits and add carry bits
245 sum = (sum >> 16) + (sum & 0xffff);
246 sum += (sum >> 16);
247
248 // Take one's complement
249 sum = ~sum;
250 return (u16) sum;
251}
u8 checksum
Definition IntelACPI.h:1
u32 getNextInode()
Get next unused inode.
FileSystem::Result unregisterFile(const char *path)
Remove a File from the FileSystemServer.
const char * getMountPath() const
Get mount path.
FileSystem::Result registerDirectory(Directory *dir, const char *path)
Register a new Directory.
FileSystem::Result registerFile(File *file, const char *path)
Register a new File.
Iterate through a HashTable.
virtual bool hasCurrent() const
Check if there is a current item.
virtual const V * get(const K &key) const
Returns the first value for the given key.
Definition HashTable.h:287
virtual bool insert(const K &key, const V &value)
Inserts the given item to the HashTable.
Definition HashTable.h:133
Abstract Input/Output buffer.
Definition IOBuffer.h:38
FileSystem::Result read(void *buffer, const Size size, const Size offset=ZERO)
Read bytes from the I/O buffer.
Definition IOBuffer.cpp:156
static const String toString(const Address address)
Convert address to string.
Definition IPV4.cpp:82
@ UDP
Definition IPV4.h:56
virtual bool insert(Size &position, T *item)
Adds the given item, if possible.
Definition Index.h:60
virtual bool remove(const Size position)
Removes the item at the given position.
Definition Index.h:143
Network Device abstract class.
virtual FileSystem::Result transmit(NetworkQueue::Packet *packet)=0
Add a network packet to the transmit queue.
Network protocol abstraction class.
NetworkProtocol & m_parent
Parent upper-layer protocol instance.
NetworkDevice & m_device
Network device instance.
virtual FileSystem::Result getTransmitPacket(NetworkQueue::Packet **pkt, const void *address, const Size addressSize, const Identifier protocol, const Size payloadSize)
Get a new packet for transmission.
NetworkServer & m_server
Network server instance.
virtual const Size getMaximumPacketSize() const
Get maximum packet size.
Networking server.
ProcessID getProcessID() const
Get owner ProcessID.
Abstraction of strings.
Definition String.h:42
User Datagram Protocol (UDP).
Definition UDPFactory.h:39
User Datagram Protocol (UDP) socket.
Definition UDPSocket.h:43
static const u16 checksum(const IPV4::Header *ip, const Header *header, const Size datalen)
Calculate ICMP checksum.
Definition UDP.cpp:224
FileSystem::Result sendPacket(const NetworkClient::SocketInfo *src, const NetworkClient::SocketInfo *dest, IOBuffer &buffer, const Size size, const Size offset)
Send packet.
Definition UDP.cpp:137
UDPFactory * m_factory
Factory for creating new UDP sockets.
Definition UDP.h:163
UDPSocket * createSocket(String &path, const ProcessID pid)
Creates an UDP socket.
Definition UDP.cpp:47
static const ulong calculateSum(const u16 *ptr, const Size bytes)
Calculate sum of artibrary data.
Definition UDP.cpp:202
void unregisterSockets(const ProcessID pid)
Remove sockets for a process.
Definition UDP.cpp:82
FileSystem::Result bind(UDPSocket *sock, const u16 port)
Bind to UDP port.
Definition UDP.cpp:188
virtual FileSystem::Result initialize()
Perform initialization.
Definition UDP.cpp:36
Index< UDPSocket, MaxUdpSockets > m_sockets
Contains all UDP sockets.
Definition UDP.h:166
virtual ~UDP()
Destructor.
Definition UDP.cpp:32
static const Size MaxUdpSockets
Definition UDP.h:45
HashTable< u16, UDPSocket * > m_ports
Maps UDP ports to UDP sockets.
Definition UDP.h:169
virtual FileSystem::Result process(const NetworkQueue::Packet *pkt, const Size offset)
Process incoming network packet.
Definition UDP.cpp:117
u32 ProcessID
Process Identification Number.
Definition Types.h:140
const u32 read32(const void *data)
Read 32-bit integer (no conversion)
Definition ByteOrder.h:242
#define ERROR(msg)
Output an error message.
Definition Log.h:61
#define be16_to_cpu(x)
Big endian 16-bit to CPU byte order.
Definition ByteOrder.h:207
unsigned long ulong
Unsigned long number.
Definition Types.h:47
unsigned int uint
Unsigned integer number.
Definition Types.h:44
const u16 read16(const void *data)
Read 16-bit integer (no conversion)
Definition ByteOrder.h:256
unsigned short u16
Unsigned 16-bit number.
Definition Types.h:56
void write16(void *data, const u16 input)
Write 16-bit integer (no conversion)
Definition ByteOrder.h:305
unsigned int Size
Any sane size indicator cannot go negative.
Definition Types.h:128
const u8 read8(const void *data)
Read 8-bit integer.
Definition ByteOrder.h:270
#define ZERO
Zero value.
Definition Macros.h:43
void writeBe16(void *data, const u16 input)
Write 16-bit big endian integer.
Definition ByteOrder.h:471
#define DEBUG(msg)
Output a debug message to standard output.
Definition Log.h:89
unsigned char u8
Unsigned 8-bit number.
Definition Types.h:59
Result
Result code for filesystem Actions.
Definition FileSystem.h:53
@ InvalidArgument
Definition FileSystem.h:55
Ethernet network packet header.
Definition Ethernet.h:65
IP network packet header.
Definition IPV4.h:67
Address destination
Definition IPV4.h:77
Address source
Definition IPV4.h:76
Pseudo Header.
Definition IPV4.h:88
Address source
Definition IPV4.h:89
Address destination
Definition IPV4.h:90
Socket information.
Represents a network packet.
Packet header format.
Definition UDP.h:53
u16 checksum
Definition UDP.h:57
u16 sourcePort
Definition UDP.h:54
u16 length
Definition UDP.h:56
u16 destPort
Definition UDP.h:55