FreeNOS
NetSend.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2021 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 <MemoryBlock.h>
19#include <NetworkClient.h>
20#include <NetworkSocket.h>
21#include <String.h>
22#include <sys/socket.h>
23#include <string.h>
24#include <errno.h>
25#include "NetSend.h"
26
27NetSend::NetSend(int argc, char **argv)
28 : POSIXApplication(argc, argv)
29{
30 parser().setDescription("send network packets");
31 parser().registerPositional("DEVICE", "device name of network adapter");
32 parser().registerPositional("HOST", "host address to send to");
33 parser().registerPositional("PORT", "UDP port to use");
34 parser().registerPositional("COUNT", "number of packets to send");
35}
36
40
42{
43 const char *dev = arguments().get("DEVICE");
44 const u16 port = String(arguments().get("PORT")).toLong();
45
46 DEBUG("");
47
48 // Create a network client
49 m_client = new NetworkClient(dev);
50
51 // Initialize networking client
53 if (result != NetworkClient::Success)
54 {
55 ERROR("failed to initialize network client for device "
56 << dev << ": result = " << (int) result);
57 return IOError;
58 }
59
60 // Create an UDP socket
62 if (result != NetworkClient::Success)
63 {
64 ERROR("failed to create UDP socket on device " << dev <<
65 ": result = " << (int) result);
66 return IOError;
67 }
68
69 // Bind to a local port.
70 result = m_client->bindSocket(m_socket, 0, port);
71 if (result != NetworkClient::Success)
72 {
73 ERROR("failed to bind socket to UDP port " << port <<
74 " on device " << dev << ": result = " << (int) result);
75 return IOError;
76 }
77
78 return Success;
79}
80
82{
83 const IPV4::Address host = IPV4::toAddress(arguments().get("HOST"));
84 const u16 port = String(arguments().get("PORT")).toLong();
85 const Size count = String(arguments().get("COUNT")).toLong();
86
87 DEBUG(" host = " << *IPV4::toString(host) << "port = " << port << " count = " << count);
88
89 // Prepare the socket address to send to
90 struct sockaddr addr;
91 addr.addr = host;
92 addr.port = port;
93
94 // Prepare I/O vector with generated packets for sending
96 static struct iovec vec[QueueSize];
97
98 for (Size i = 0; i < QueueSize; i++)
99 {
100 MemoryBlock::set(pkts[i], i, PacketSize);
101
102 vec[i].iov_base = pkts[i];
103 vec[i].iov_len = PacketSize;
104 }
105
106 // Keep sending packets until we reach the number to send
107 for (Size i = 0; i < count;)
108 {
109 const Size num = count - i >= QueueSize ?
110 QueueSize : count - i;
111
112 const Result r = udpSendMultiple(vec, num, addr);
113 if (r != Success)
114 {
115 ERROR("failed to send multiple UDP packets: result = " << (int) r);
116 return r;
117 }
118
119 i += num;
120 }
121
122 return Success;
123}
124
126 const Size count,
127 const struct sockaddr & addr) const
128{
129 struct msghdr msg;
130
131 DEBUG("host = " << *IPV4::toString(addr.addr) << " port = " << addr.port << " count = " << count);
132
133 // Prepare the message header
134 msg.msg_name = (void *) &addr;
135 msg.msg_namelen = sizeof(addr);
136 msg.msg_iov = (struct iovec *) vec;
137 msg.msg_iovlen = count;
138
139 // Send the packet
140 int result = ::sendmsg(m_socket, &msg, 0);
141 if (result <= 0)
142 {
143 ERROR("failed to send multiple UDP datagrams: " << strerror(errno));
144 return IOError;
145 }
146
147 return Success;
148}
Result
Result codes.
Definition Application.h:54
const ArgumentContainer & arguments() const
Get program arguments.
ArgumentParser & parser()
Get program arguments parser.
const char * get(const char *name) const
Get argument by name.
void setDescription(const String &desc)
Set program description.
Result registerPositional(const char *name, const char *description, Size count=1)
Register a positional argument.
static const String toString(const Address address)
Convert address to string.
Definition IPV4.cpp:82
u32 Address
IP-address.
Definition IPV4.h:47
static const Address toAddress(const char *address)
Convert string to IPV4 address.
Definition IPV4.cpp:94
static void * set(void *dest, int ch, unsigned count)
Fill memory with a constant byte.
virtual Result exec()
Execute the application event loop.
Definition NetSend.cpp:81
virtual Result initialize()
Initialize the application.
Definition NetSend.cpp:41
Result udpSendMultiple(const struct iovec *vec, const Size count, const struct sockaddr &addr) const
Send multiple UDP packets.
Definition NetSend.cpp:125
int m_socket
UDP socket.
Definition NetSend.h:94
static const Size PacketSize
Size of each packet to send in bytes.
Definition NetSend.h:38
static const Size QueueSize
Number of packets to submit for transmission each iteration.
Definition NetSend.h:41
virtual ~NetSend()
Class destructor.
Definition NetSend.cpp:37
NetworkClient * m_client
Network client.
Definition NetSend.h:91
NetSend(int argc, char **argv)
Class constructor.
Definition NetSend.cpp:27
Networking Client implementation.
Result bindSocket(const int sock, const IPV4::Address addr=0, const u16 port=0)
Bind socket to address/port.
Result initialize()
Perform initialization.
Result
Result codes.
Result createSocket(const SocketType type, int *socket)
Create new socket.
static const Size PayloadBufferSize
Size of payload memory buffer.
static const Size MaxPackets
Maximum number of packets available.
POSIX-compatible application.
Abstraction of strings.
Definition String.h:42
long toLong(const Number::Base base=Number::Dec) const
Convert the String to a signed long integer.
Definition String.cpp:456
C char * strerror(int errnum)
The strerror function maps the number in errnum to a message string.
Definition strerror.cpp:20
C int errno
The lvalue errno is used by many functions to return error values.
C int sendmsg(int sockfd, const struct msghdr *msg, int flags)
Send multiple datagrams to a remote host.
Definition sendmsg.cpp:24
#define ERROR(msg)
Output an error message.
Definition Log.h:61
unsigned short u16
Unsigned 16-bit number.
Definition Types.h:56
unsigned int Size
Any sane size indicator cannot go negative.
Definition Types.h:128
#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
Input/Output vector for multi-packet operations.
Definition socket.h:45
void * iov_base
Definition socket.h:46
size_t iov_len
Definition socket.h:47
Describes one or more datagrams.
Definition socket.h:56
struct iovec * msg_iov
Definition socket.h:59
socklen_t msg_namelen
Definition socket.h:58
void * msg_name
Definition socket.h:57
size_t msg_iovlen
Definition socket.h:60
Defines a socket address and port pair.
Definition socket.h:36
u32 addr
Definition socket.h:37
u16 port
Definition socket.h:38