implemented UDPv4 socket class
Stefan Schuermans

Stefan Schuermans commited on 2011-11-12 22:47:21
Showing 4 changed files, with 227 additions and 35 deletions.

... ...
@@ -82,27 +82,5 @@ std::string Udp4Addr::toStr() const
82 82
   return strm.str();
83 83
 }
84 84
 
85
-/**
86
- * @brief set to sockaddr
87
- * @parma[in] addr sockaddr structure to use
88
- * @return if using sockaddr was successful
89
- */
90
-bool Udp4Addr::fromSockaddr(const struct sockaddr &addr)
91
-{
92
-  if (addr.sa_family != AF_INET)
93
-    return false;
94
-  m_addr = *(const struct sockaddr_in *)&addr;
95
-  return true;
96
-}
97
-
98
-/**
99
- * @brief convert to sockaddr
100
- * @return sockaddr structure
101
- */
102
-const struct sockaddr & Udp4Addr::toSockaddr() const
103
-{
104
-  return *(const struct sockaddr *)&m_addr;
105
-}
106
-
107 85
 } // namespace Blinker
108 86
 
... ...
@@ -42,21 +42,10 @@ public:
42 42
    */
43 43
   virtual std::string toStr() const;
44 44
 
45
-  /**
46
-   * @brief set to sockaddr
47
-   * @parma[in] addr sockaddr structure to use
48
-   * @return if using sockaddr was successful
49
-   */
50
-  virtual bool fromSockaddr(const struct sockaddr &addr);
51
-
52
-  /**
53
-   * @brief convert to sockaddr
54
-   * @return sockaddr structure
55
-   */
56
-  virtual const struct sockaddr & toSockaddr() const;
57
-
58 45
 protected:
59 46
   struct sockaddr_in m_addr;
47
+
48
+friend class Udp4Sock;
60 49
 }; // class Udp4Addr
61 50
 
62 51
 } // namespace Blinker
... ...
@@ -0,0 +1,152 @@
1
+/* Blinker
2
+   Copyright 2011 Stefan Schuermans <stefan@blinkenarea.org>
3
+   Copyleft GNU public license - http://www.gnu.org/copyleft/gpl.html
4
+   a blinkenarea.org project */
5
+
6
+#include <fcntl.h>
7
+#include <netinet/in.h>
8
+#include <string>
9
+#include <sys/socket.h>
10
+#include <sys/types.h>
11
+#include <unistd.h>
12
+
13
+#include "Io.h"
14
+#include "Udp4Addr.h"
15
+#include "Udp4Sock.h"
16
+
17
+namespace Blinker {
18
+
19
+/// constructor
20
+Udp4Sock::Udp4Sock()
21
+{
22
+  int flags, opt;
23
+
24
+  // create socket
25
+  m_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
26
+  if (m_fd == -1)
27
+    return;
28
+
29
+  // switch to nonblocking mode
30
+  flags = fcntl(m_fd, F_GETFL);
31
+  if (flags == -1 || fcntl(m_fd, F_SETFL, flags | O_NONBLOCK) != 0) {
32
+    close(m_fd);
33
+    m_fd = -1;
34
+    return;
35
+  }
36
+
37
+  // enable address re-use
38
+  if (setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) != 0) {
39
+    close(m_fd);
40
+    m_fd = -1;
41
+    return;
42
+  }
43
+}
44
+
45
+/// destructor
46
+Udp4Sock::~Udp4Sock()
47
+{
48
+  // exit if not initialized
49
+  if (m_fd == -1)
50
+    return;
51
+
52
+  // shutdown and close socket
53
+  shutdown(m_fd, SHUT_RDWR);
54
+  close(m_fd);
55
+  m_fd = -1;
56
+}
57
+
58
+/**
59
+ * @brief get address the socket is bound to
60
+ * @param[out] addr local addess the socket is bound to
61
+ * @return if local address could be obtained
62
+ */
63
+bool Udp4Sock::getAddr(Udp4Addr &addr)
64
+{
65
+  struct sockaddr * sockaddr;
66
+  socklen_t socklen;
67
+
68
+  // exit with error if not initialized
69
+  if (m_fd == -1)
70
+    return false;
71
+
72
+  // get local name of socket
73
+  sockaddr = (struct sockaddr *)&addr.m_addr;
74
+  socklen = sizeof(addr.m_addr);
75
+  if (getsockname(m_fd, sockaddr, &socklen) != 0)
76
+    return false;
77
+  return socklen <= sizeof(addr.m_addr); // check if not truncated
78
+}
79
+
80
+/**
81
+ * @brief bind socket
82
+ * @param[in] addr local address to bind to
83
+ * @return if binding succeeded
84
+ */
85
+bool Udp4Sock::bind(const Udp4Addr &addr)
86
+
87
+{
88
+  const struct sockaddr * sockaddr;
89
+  socklen_t socklen;
90
+
91
+  // exit with error if not initialized
92
+  if (m_fd == -1)
93
+    return false;
94
+
95
+  // bind
96
+  sockaddr = (const struct sockaddr *)&addr.m_addr;
97
+  socklen = sizeof(addr.m_addr);
98
+  return ::bind(m_fd, sockaddr, socklen) == 0;
99
+}
100
+
101
+/**
102
+ * @brief send to socket
103
+ * @param[in] data data to send in message
104
+ * @param[in] addr address the message should be sent to
105
+ * @return if the message could be sent
106
+ */
107
+bool Udp4Sock::send(const std::string &data, const Udp4Addr &addr)
108
+{
109
+  const struct sockaddr * sockaddr;
110
+  socklen_t socklen;
111
+  ssize_t len;
112
+
113
+  // exit with error if not initialized
114
+  if (m_fd == -1)
115
+    return false;
116
+
117
+  // send message
118
+  sockaddr = (const struct sockaddr *)&addr.m_addr;
119
+  socklen = sizeof(addr.m_addr);
120
+  len = sendto(m_fd, data.c_str(), data.size(), 0, sockaddr, socklen);
121
+  return len == (ssize_t)data.size();
122
+}
123
+
124
+/**
125
+ * @brief receive from socket
126
+ * @param[out] data data in received message
127
+ * @param[out] addr address the message has been received from
128
+ * @return if a message has been received
129
+ */
130
+bool Udp4Sock::recv(std::string &data, Udp4Addr &addr)
131
+{
132
+  char buf[65536];
133
+  struct sockaddr * sockaddr;
134
+  socklen_t socklen;
135
+  ssize_t len;
136
+
137
+  // exit with error if not initialized
138
+  if (m_fd == -1)
139
+    return false;
140
+
141
+  // receive message
142
+  sockaddr = (struct sockaddr *)&addr.m_addr;
143
+  socklen = sizeof(addr.m_addr);
144
+  len = recvfrom(m_fd, buf, sizeof(buf), 0, sockaddr, &socklen);
145
+  if (len < 0 || socklen > sizeof(addr.m_addr)) // error or address truncated
146
+    return false;
147
+  data.assign(buf, len);
148
+  return true;
149
+}
150
+
151
+} // namespace Blinker
152
+
... ...
@@ -0,0 +1,73 @@
1
+/* Blinker
2
+   Copyright 2011 Stefan Schuermans <stefan@blinkenarea.org>
3
+   Copyleft GNU public license - http://www.gnu.org/copyleft/gpl.html
4
+   a blinkenarea.org project */
5
+
6
+#ifndef UDP4SOCK_H
7
+#define UDP4SOCK_H
8
+
9
+#include <string>
10
+
11
+#include "Io.h"
12
+#include "Udp4Addr.h"
13
+
14
+namespace Blinker {
15
+
16
+/**
17
+ * @brief UDP v4 socket
18
+ *
19
+ * UDP v4 socket in non-blcoking mode with address re-usage enabled
20
+ */
21
+class Udp4Sock: public Io
22
+{
23
+public:
24
+  /// constructor
25
+  Udp4Sock();
26
+
27
+  /// destructor
28
+  ~Udp4Sock();
29
+
30
+private:
31
+  /// copy constructor disabled
32
+  Udp4Sock(const Io &that);
33
+
34
+  /// assignment operator disabled
35
+  const Udp4Sock & operator=(const Udp4Sock &that);
36
+
37
+public:
38
+  /**
39
+   * @brief get address the socket is bound to
40
+   * @param[out] addr local addess the socket is bound to
41
+   * @return if local address could be obtained
42
+   */
43
+  bool getAddr(Udp4Addr &addr);
44
+
45
+  /**
46
+   * @brief bind socket
47
+   * @param[in] addr local address to bind to
48
+   * @return if binding succeeded
49
+   */
50
+  bool bind(const Udp4Addr &addr);
51
+
52
+  /**
53
+   * @brief send to socket
54
+   * @param[in] data data to send in message
55
+   * @param[in] addr address the message should be sent to
56
+   * @return if the message could be sent
57
+   */
58
+  bool send(const std::string &data, const Udp4Addr &addr);
59
+
60
+  /**
61
+   * @brief receive from socket
62
+   * @param[out] data data in received message
63
+   * @param[out] addr address the message has been received from
64
+   * @return if a message has been received
65
+   */
66
+  bool recv(std::string &data, Udp4Addr &addr);
67
+
68
+}; // class UdpSock
69
+
70
+} // namespace Blinker
71
+
72
+#endif // #ifndef UDP4SOCK_H
73
+
0 74