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 
27 NetSend::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 
38 {
39 }
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 }
NetworkClient::Result
Result
Result codes.
Definition: NetworkClient.h:99
ArgumentContainer::get
const char * get(const char *name) const
Get argument by name.
Definition: ArgumentContainer.cpp:49
NetworkClient::Success
@ Success
Definition: NetworkClient.h:101
NetworkClient::initialize
Result initialize()
Perform initialization.
Definition: NetworkClient.cpp:35
NetworkClient::createSocket
Result createSocket(const SocketType type, int *socket)
Create new socket.
Definition: NetworkClient.cpp:80
errno
C int errno
The lvalue errno is used by many functions to return error values.
NetSend::m_client
NetworkClient * m_client
Network client.
Definition: NetSend.h:91
MemoryBlock::set
static void * set(void *dest, int ch, unsigned count)
Fill memory with a constant byte.
Definition: MemoryBlock.cpp:25
string.h
String
Abstraction of strings.
Definition: String.h:41
sockaddr::port
u16 port
Definition: socket.h:38
NetSend::m_socket
int m_socket
UDP socket.
Definition: NetSend.h:94
NetworkQueue::MaxPackets
static const Size MaxPackets
Maximum number of packets available.
Definition: NetworkQueue.h:45
NetSend::NetSend
NetSend(int argc, char **argv)
Class constructor.
Definition: NetSend.cpp:27
NetSend.h
POSIXApplication
POSIX-compatible application.
Definition: POSIXApplication.h:35
msghdr::msg_iov
struct iovec * msg_iov
Definition: socket.h:59
Application::Success
@ Success
Definition: Application.h:55
MemoryBlock.h
Application::arguments
const ArgumentContainer & arguments() const
Get program arguments.
Definition: Application.cpp:112
ArgumentParser::setDescription
void setDescription(const String &desc)
Set program description.
Definition: ArgumentParser.cpp:95
sockaddr
Defines a socket address and port pair.
Definition: socket.h:35
msghdr::msg_iovlen
size_t msg_iovlen
Definition: socket.h:60
Application::IOError
@ IOError
Definition: Application.h:57
DEBUG
#define DEBUG(msg)
Output a debug message to standard output.
Definition: Log.h:89
msghdr
Describes one or more datagrams.
Definition: socket.h:55
u16
unsigned short u16
Unsigned 16-bit number.
Definition: Types.h:56
IPV4::toAddress
static const Address toAddress(const char *address)
Convert string to IPV4 address.
Definition: IPV4.cpp:94
strerror
char * strerror(int errnum)
The strerror function maps the number in errnum to a message string.
Definition: strerror.cpp:20
NetSend::udpSendMultiple
Result udpSendMultiple(const struct iovec *vec, const Size count, const struct sockaddr &addr) const
Send multiple UDP packets.
Definition: NetSend.cpp:125
iovec::iov_base
void * iov_base
Definition: socket.h:46
Size
unsigned int Size
Any sane size indicator cannot go negative.
Definition: Types.h:128
msghdr::msg_name
void * msg_name
Definition: socket.h:57
Application::Result
Result
Result codes.
Definition: Application.h:53
NetSend::initialize
virtual Result initialize()
Initialize the application.
Definition: NetSend.cpp:41
IPV4::Address
u32 Address
IP-address.
Definition: IPV4.h:47
NetworkClient
Networking Client implementation.
Definition: NetworkClient.h:44
iovec
Input/Output vector for multi-packet operations.
Definition: socket.h:44
NetworkClient::bindSocket
Result bindSocket(const int sock, const IPV4::Address addr=0, const u16 port=0)
Bind socket to address/port.
Definition: NetworkClient.cpp:123
iovec::iov_len
size_t iov_len
Definition: socket.h:47
ArgumentParser::registerPositional
Result registerPositional(const char *name, const char *description, Size count=1)
Register a positional argument.
Definition: ArgumentParser.cpp:119
sockaddr::addr
u32 addr
Definition: socket.h:37
IPV4::toString
static const String toString(const Address address)
Convert address to string.
Definition: IPV4.cpp:82
Application::parser
ArgumentParser & parser()
Get program arguments parser.
Definition: Application.cpp:102
ERROR
#define ERROR(msg)
Output an error message.
Definition: Log.h:61
u8
unsigned char u8
Unsigned 8-bit number.
Definition: Types.h:59
NetSend::PacketSize
static const Size PacketSize
Size of each packet to send in bytes.
Definition: NetSend.h:38
socket.h
String.h
NetSend::QueueSize
static const Size QueueSize
Number of packets to submit for transmission each iteration.
Definition: NetSend.h:41
NetworkQueue::PayloadBufferSize
static const Size PayloadBufferSize
Size of payload memory buffer.
Definition: NetworkQueue.h:42
NetSend::exec
virtual Result exec()
Execute the application event loop.
Definition: NetSend.cpp:81
NetworkClient.h
msghdr::msg_namelen
socklen_t msg_namelen
Definition: socket.h:58
NetSend::~NetSend
virtual ~NetSend()
Class destructor.
Definition: NetSend.cpp:37
NetworkClient::UDP
@ UDP
Definition: NetworkClient.h:93
sendmsg
C int sendmsg(int sockfd, const struct msghdr *msg, int flags)
Send multiple datagrams to a remote host.
Definition: sendmsg.cpp:24
NetworkSocket.h
errno.h
String::toLong
long toLong(const Number::Base base=Number::Dec) const
Convert the String to a signed long integer.
Definition: String.cpp:456