1 /** 2 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 * SPDX-License-Identifier: Apache-2.0. 4 */ 5 6 #pragma once 7 8 #include <aws/core/Core_EXPORTS.h> 9 #include <aws/core/utils/memory/stl/AWSString.h> 10 #include <cstdint> 11 struct sockaddr; 12 13 namespace Aws 14 { 15 namespace Net 16 { 17 // 8K is aligned with default monitoring packet size. 18 const static size_t UDP_BUFFER_SIZE = 8192; 19 /** 20 * SimpleUDP definition. 21 */ 22 class AWS_CORE_API SimpleUDP 23 { 24 public: 25 /** 26 * @brief Constructor of SimpleUDP 27 * @param addressFamily, AF_INET for IPV4 or AF_INET6 for IPV6 28 * @param sendBufSize, if nonzero, try set socket's send buffer size to this value. 29 * @param receieveBufSize, if nonzero, try set socket's receive buffer size to this value. 30 * @param nonBlocking, if it is true, implementation will try to create a non-blocking underlying UDP socket. 31 * Implementation should create and set the underlying udp socket. 32 */ 33 SimpleUDP(int addressFamily, size_t sendBufSize = UDP_BUFFER_SIZE, size_t receiveBufSize = UDP_BUFFER_SIZE, bool nonBlocking = true); 34 35 /** 36 * @brief An easy constructor of an IPV4 or IPV6 SimpleUDP 37 * @param addressFamily, either AF_INET for IPV4 or AF_INET6 for IPV6 38 * @param sendBufSize, if nonzero, try set socket's send buffer size to this value. 39 * @param receieveBufSize, if nonzero, try set socket's receive buffer size to this value. 40 * @param nonBlocking, if it is true, implementation will try to create a non-blocking underlying UDP socket. 41 * Implementation should create and set the underlying udp socket. 42 */ 43 SimpleUDP(bool IPV4 = true, size_t sendBufSize = UDP_BUFFER_SIZE, size_t receiveBufSize = UDP_BUFFER_SIZE, bool nonBlocking = true); 44 45 /** 46 * @brief An easy constructor of SimpleUDP based on host and port 47 * @param host, the host that packets will be sent to, could be ipv4 or ipv6 address, or a hostname 48 * Note that "localhost" is not necessarily bind to 127.0.0.1, it could bind to ipv6 address ::1, or other type of ip addresses. If you pass localhost here, we will go through getaddrinfo procedure on Linux and Windows. 49 * @param port, the port number that the host listens on. 50 * @param sendBufSize, if nonzero, try set socket's send buffer size to this value. 51 * @param receieveBufSize, if nonzero, try set socket's receive buffer size to this value. 52 * @param nonBlocking, if it is true, implementation will try to create a non-blocking underlying UDP socket. 53 * Implementation should create and set the underlying udp socket. 54 */ 55 SimpleUDP(const char* host, unsigned short port, size_t sendBufSize = UDP_BUFFER_SIZE, size_t receiveBufSize = UDP_BUFFER_SIZE, bool nonBlocking = true); 56 57 ~SimpleUDP(); 58 59 /** 60 * @brief Connect underlying udp socket to server specified in address. 61 * @param address, the server's address info. 62 * @param addressLength, length of address, structure of address can vary. 63 * @return 0 on success, -1 on error, check errno for detailed error information. 64 */ 65 int Connect(const sockaddr* address, size_t addressLength); 66 67 /** 68 * @brief An easy way to connect to host 69 * @param hostIP, a valid ipv4 or ipv6 address. The address type should match the m_addressFamily type settled during construction. 70 * Otherwise the connection will fail. 71 * @param port, the port that host listens on. 72 */ 73 int ConnectToHost(const char* hostIP, unsigned short port) const; 74 75 /** 76 * @brief An easy way to connect to 127.0.0.1 or ::1 based on m_addressFamily 77 */ 78 int ConnectToLocalHost(unsigned short port) const; 79 80 /** 81 * @brief Bind underlying udp socket to an address. 82 * @param address, the server's address info. 83 * @param addressLength, length of address, structure of address can vary. 84 * @return 0 on success, -1 on error, check errno for detailed error information. 85 */ 86 int Bind(const sockaddr* address, size_t addressLength) const; 87 88 /** 89 * @brief An easy way to bind to localhost 90 */ 91 int BindToLocalHost(unsigned short port) const; 92 93 /** 94 * @brief Send data to server without specifying address, only usable if hostIP and port are available. 95 * @param data, the data you want to send. 96 * @param dataLen, the length of data you want to send. On Windows, dataLen larger than INT32_MAX will cause undefined behavior 97 * @return 0 on success, -1 on error, check errno for detailed error information. 98 */ 99 int SendData(const uint8_t* data, size_t dataLen) const; 100 101 /** 102 * @brief Send data to server. 103 * @param address, the server's address info. 104 * @param addressLength, length of address, structure of address can vary. 105 * @param data, the memory address of the data you want to send. 106 * @param dataLen, the length of data you want to send. On Windows, dataLen larger than INT32_MAX will cause undefined behavior 107 * @return 0 on success, -1 on error check errno for detailed error information. 108 */ 109 int SendDataTo(const sockaddr* address, size_t addressLength, const uint8_t* data, size_t dataLen) const; 110 111 /** 112 * @brief An easy way to send data to localhost, when the underlying udp is connected, call this function will 113 * send the data to where it connects to, not essentially to localhost. when it's not connected, it will send data 114 * to localhost, but this call will not connect underlying socket to localhost for you. 115 * @param data, the memory address of the data you want to send. 116 * @param dataLen, the length of data you want to send. On Windows, dataLen larger than INT32_MAX will cause undefined behavior 117 * @param port, port of localhost. 118 * @return 0 on success, -1 on error, check errno for detailed error information. 119 */ 120 int SendDataToLocalHost(const uint8_t* data, size_t dataLen, unsigned short port) const; 121 122 /** 123 * @brief Receive data from unique address specified in ConnectWithServer call. 124 * this function is equivalent to call ReceiveDataFrom(nullptr, 0, data, dataLen, flags). 125 * @param buffer, the memory address where you want to store received data. 126 * @param bufferLen, the size of data buffer. 127 * @return -1 on failure, check errno for detailed error information, on success, returns the actual bytes of data received 128 */ 129 int ReceiveData(uint8_t* buffer, size_t bufferLen) const; 130 131 /** 132 * @brief Receive data from network. 133 * @param address, if not null and underlying implementation supply the incoming data's source address, this will be filled with source address info. 134 * @param addressLength, the size of source adddress, should not be null. 135 * @param buffer, the memory address where you want to store received data. 136 * @param bufferLen, the size of data buffer. 137 * @return -1 on failure, check errno for detailed error information, on success, returns the actual bytes of data received. 138 */ 139 int ReceiveDataFrom(sockaddr* address, size_t* addressLength, uint8_t* buffer, size_t bufferLen) const; 140 141 /** 142 * Gets the AddressFamily used for the underlying socket. E.g. AF_INET, AF_INET6 etc. 143 */ GetAddressFamily()144 inline int GetAddressFamily() const { return m_addressFamily; } 145 146 /** 147 * Is the underlying socket connected with a remote address 148 */ IsConnected()149 inline bool IsConnected() const { return m_connected; } 150 151 private: 152 void CreateSocket(int addressFamily, size_t sendBufSize, size_t receiveBufSize, bool nonBlocking); GetUnderlyingSocket()153 int GetUnderlyingSocket() const { return m_socket; } SetUnderlyingSocket(int socket)154 void SetUnderlyingSocket(int socket) { m_socket = socket; } 155 int m_addressFamily; 156 // if not connected, you can't perform SendData, if connected, SendDataTo will call SendData 157 mutable bool m_connected; 158 int m_socket; 159 unsigned short m_port; 160 Aws::String m_hostIP; 161 }; 162 } 163 } 164