add IPv6 support to BlinkenSend and BlinkenRecv
Stefan Schuermans

Stefan Schuermans commited on 2014-01-02 20:51:18
Showing 7 changed files, with 256 additions and 85 deletions.

... ...
@@ -18,14 +18,14 @@
18 18
 #endif
19 19
 
20 20
 #include <BlinkenLib/BlinkenLib.h>
21
+#include "Tools2.h"
21 22
 
22 23
 int main(int argCnt, char **args)
23 24
 {
24
-  int i, bound, val, timeout;
25
-  SOCKET udpSocket;
26
-  char txt[64];
27
-  unsigned short port;
25
+  int i, bound, val, timeout, ipv6;
26
+  SOCKET udpSocket, tmpSock;
28 27
   struct sockaddr_in addr;
28
+  struct sockaddr_in6 addr6;
29 29
   stBlinkenMovie *pMovie;
30 30
 
31 31
   // print info
... ...
@@ -47,6 +47,10 @@ int main(int argCnt, char **args)
47 47
 #endif
48 48
     printf("syntax: %s <parameter> [...]\n\n"
49 49
            "parameters:\n"
50
+           "  -4\n"
51
+           "     use IPv4 (default for now, subject to change)\n"
52
+           "  -6\n"
53
+           "     use IPv6\n"
50 54
            "  -l [<ip>:]<port>\n"
51 55
            "     local address (defaults to 0.0.0.0:2323)\n"
52 56
            "     must occur before -r and -o, may only occur once\n"
... ...
@@ -66,10 +70,11 @@ int main(int argCnt, char **args)
66 70
   }
67 71
 #endif
68 72
 
69
-  // create udp socket
73
+  // create UDP socket
74
+  ipv6 = 0;
70 75
   udpSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
71 76
   if (udpSocket == INVALID_SOCKET) {
72
-    printf("cannot create UDP socket\n");
77
+    printf("cannot create IPv4 UDP socket\n");
73 78
 #ifdef WIN32
74 79
     WSACleanup();
75 80
 #endif
... ...
@@ -81,28 +86,51 @@ int main(int argCnt, char **args)
81 86
   timeout = 5000;
82 87
   for (i = 1; i < argCnt; i++) {
83 88
 
89
+    // IPv4
90
+    if (strcmp(args[i], "-4") == 0) {
91
+      if (ipv6) {
92
+        // replace socket with new IPv4 UDP socket
93
+        tmpSock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
94
+        if (tmpSock != INVALID_SOCKET) {
95
+          close(udpSocket);
96
+          udpSocket = tmpSock;
97
+          ipv6 = 0;
98
+        } else {
99
+          printf("cannot create IPv4 UDP socket\n");
100
+        }
101
+      }
102
+    }
103
+    // IPv6
104
+    else if (strcmp(args[i], "-6") == 0) {
105
+      if (!ipv6) {
106
+        // replace socket with new IPv6 UDP socket
107
+        tmpSock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
108
+        if (tmpSock != INVALID_SOCKET) {
109
+          close(udpSocket);
110
+          udpSocket = tmpSock;
111
+          ipv6 = 1;
112
+        } else {
113
+          printf("cannot create IPv6 UDP socket\n");
114
+        }
115
+      }
116
+    }
84 117
     // local address
85
-    if (strcmp(args[i], "-l") == 0) {
118
+    else if (strcmp(args[i], "-l") == 0) {
86 119
       if (i + 1 < argCnt) {
87 120
         i++;
88
-        if (sscanf(args[i], "%32[0-9.]:%hu", txt, &port) == 2) {
89
-          addr.sin_family = AF_INET;
90
-          addr.sin_port = htons(port);
91
-          addr.sin_addr.s_addr = inet_addr(txt);
92
-          if (bind(udpSocket, (struct sockaddr *)&addr, sizeof(addr)) != 0)
121
+        if (!ipv6) {
122
+          if (!txt2addr(args[i], &addr) ||
123
+              bind(udpSocket, (struct sockaddr *)&addr, sizeof(addr)) != 0)
93 124
             printf("could not set local address to \"%s\"\n", args[i]);
94 125
           else
95 126
             bound = 1;
96
-        } else if (sscanf(args[i], "%hu", &port) == 1) {
97
-          addr.sin_family = AF_INET;
98
-          addr.sin_port = htons(port);
99
-          addr.sin_addr.s_addr = htonl(INADDR_ANY);
100
-          if (bind(udpSocket, (struct sockaddr *)&addr, sizeof(addr)) != 0)
127
+        } else {
128
+          if (!txt2addr6(args[i], &addr6) ||
129
+              bind(udpSocket, (struct sockaddr *)&addr6, sizeof(addr6)) != 0)
101 130
             printf("could not set local address to \"%s\"\n", args[i]);
102 131
           else
103 132
             bound = 1;
104
-        } else
105
-          printf("invalid local address \"%s\"\n", args[i]);
133
+        }
106 134
       } else
107 135
         printf("missing local address for \"-l\"\n");
108 136
     }
... ...
@@ -110,20 +138,15 @@ int main(int argCnt, char **args)
110 138
     else if (strcmp(args[i], "-r") == 0) {
111 139
       if (i + 1 < argCnt) {
112 140
         i++;
113
-        if (sscanf(args[i], "%32[0-9.]:%hu", txt, &port) == 2) {
114
-          addr.sin_family = AF_INET;
115
-          addr.sin_port = htons(port);
116
-          addr.sin_addr.s_addr = inet_addr(txt);
117
-          if (connect(udpSocket, (struct sockaddr *)&addr, sizeof(addr)) != 0)
141
+        if (!ipv6) {
142
+          if (!txt2addr(args[i], &addr) ||
143
+              bind(udpSocket, (struct sockaddr *)&addr, sizeof(addr)) != 0)
118 144
             printf("could not set remote address to \"%s\"\n", args[i]);
119
-        } else if (sscanf(args[i], "%32[0-9.]", txt) == 1) {
120
-          addr.sin_family = AF_INET;
121
-          addr.sin_port = htons(23230);
122
-          addr.sin_addr.s_addr = inet_addr(txt);
123
-          if (connect(udpSocket, (struct sockaddr *)&addr, sizeof(addr)) != 0)
145
+        } else {
146
+          if (!txt2addr6(args[i], &addr6) ||
147
+              bind(udpSocket, (struct sockaddr *)&addr6, sizeof(addr6)) != 0)
124 148
             printf("could not set remote address to \"%s\"\n", args[i]);
125
-        } else
126
-          printf("invalid remote address \"%s\"\n", args[i]);
149
+        }
127 150
       } else
128 151
         printf("missing remote address for \"-r\"\n");
129 152
     }
... ...
@@ -144,15 +167,25 @@ int main(int argCnt, char **args)
144 167
         i++;
145 168
         if (!bound)     // try to bind if not bound
146 169
         {
170
+          if (!ipv6) {
147 171
             printf("no local address to receive movie for file \"%s\" to,\n"
148
-                 "  using default local address \"0.0.0.0:2323\"\n", args[i]);
149
-          addr.sin_family = AF_INET;
150
-          addr.sin_port = htons(2323);
151
-          addr.sin_addr.s_addr = htonl(INADDR_ANY);
152
-          if (bind(udpSocket, (struct sockaddr *)&addr, sizeof(addr)) != 0)
153
-            printf("could not set local address to \"0.0.0.0:2323\"\n");
172
+                   "  using default local address \"0.0.0.0:2323\"\n",
173
+                   args[i]);
174
+            if (!txt2addr("127.0.0.1:2323", &addr) ||
175
+                bind(udpSocket, (struct sockaddr *)&addr, sizeof(addr)) != 0)
176
+              printf("could not set local address to \"127.0.0.1:2323\"\n");
154 177
             else
155 178
               bound = 1;
179
+          } else {
180
+            printf("no local address to receive movie for file \"%s\" to,\n"
181
+                   "  using default local address \"[::1]:2323\"\n",
182
+                   args[i]);
183
+            if (!txt2addr6("[::1]:2323", &addr6) ||
184
+                bind(udpSocket, (struct sockaddr *)&addr6, sizeof(addr6)) != 0)
185
+              printf("could not set local address to \"[::1]:2323\"\n");
186
+            else
187
+              bound = 1;
188
+          }
156 189
         }
157 190
         if (bound) {
158 191
           printf("receiving movie for file \"%s\"...\n", args[i]);
... ...
@@ -19,16 +19,16 @@
19 19
 #endif
20 20
 
21 21
 #include <BlinkenLib/BlinkenLib.h>
22
+#include "Tools2.h"
22 23
 
23 24
 int main(int argCnt, char **args)
24 25
 {
25
-  int i, connected;
26
-  SOCKET udpSocket;
26
+  int i, connected, ipv6;
27
+  SOCKET udpSocket, tmpSock;
27 28
   etBlinkenProto proto;
28 29
   unsigned int maxidle, send_cnt, loop_cnt, loop, ui;
29
-  char txt[64];
30
-  unsigned short port;
31 30
   struct sockaddr_in addr;
31
+  struct sockaddr_in6 addr6;
32 32
   stBlinkenMovie *pMovie;
33 33
 
34 34
   // print info
... ...
@@ -50,6 +50,10 @@ int main(int argCnt, char **args)
50 50
 #endif
51 51
     printf("syntax: %s <parameter> [...]\n\n"
52 52
            "parameters:\n"
53
+           "  -4\n"
54
+           "     use IPv4 (default for now, subject to change)\n"
55
+           "  -6\n"
56
+           "     use IPv6\n"
53 57
            "  -s [<ip>:]<port>\n"
54 58
            "     source address (defaults to 0.0.0.0:0)\n"
55 59
            "     must occur before -d and -i, may only occur once\n"
... ...
@@ -75,10 +79,11 @@ int main(int argCnt, char **args)
75 79
   }
76 80
 #endif
77 81
 
78
-  // create udp socket
82
+  // create UDP socket
83
+  ipv6 = 0;
79 84
   udpSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
80 85
   if (udpSocket == INVALID_SOCKET) {
81
-    printf("cannot create UDP socket\n");
86
+    printf("cannot create IPv4 UDP socket\n");
82 87
 #ifdef WIN32
83 88
     WSACleanup();
84 89
 #endif
... ...
@@ -101,24 +106,47 @@ int main(int argCnt, char **args)
101 106
     send_cnt = 1;
102 107
     for (i = 1; i < argCnt; i++) {
103 108
 
109
+      // IPv4
110
+      if (strcmp(args[i], "-4") == 0) {
111
+        if (ipv6) {
112
+          // replace socket with new IPv4 UDP socket
113
+          tmpSock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
114
+          if (tmpSock != INVALID_SOCKET) {
115
+            close(udpSocket);
116
+            udpSocket = tmpSock;
117
+            ipv6 = 0;
118
+          } else {
119
+            printf("cannot create IPv4 UDP socket\n");
120
+          }
121
+        }
122
+      }
123
+      // IPv6
124
+      else if (strcmp(args[i], "-6") == 0) {
125
+        if (!ipv6) {
126
+          // replace socket with new IPv6 UDP socket
127
+          tmpSock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
128
+          if (tmpSock != INVALID_SOCKET) {
129
+            close(udpSocket);
130
+            udpSocket = tmpSock;
131
+            ipv6 = 1;
132
+          } else {
133
+            printf("cannot create IPv6 UDP socket\n");
134
+          }
135
+        }
136
+      }
104 137
       // source address
105
-      if (strcmp(args[i], "-s") == 0) {
138
+      else if (strcmp(args[i], "-s") == 0) {
106 139
         if (i + 1 < argCnt) {
107 140
           i++;
108
-          if (sscanf(args[i], "%32[0-9.]:%hu", txt, &port) == 2) {
109
-            addr.sin_family = AF_INET;
110
-            addr.sin_port = htons(port);
111
-            addr.sin_addr.s_addr = inet_addr(txt);
112
-            if (bind(udpSocket, (struct sockaddr *)&addr, sizeof(addr)) != 0)
141
+          if (!ipv6) {
142
+            if (!txt2addr(args[i], &addr) ||
143
+                bind(udpSocket, (struct sockaddr *)&addr, sizeof(addr)) != 0)
113 144
               printf("could not set source address to \"%s\"\n", args[i]);
114
-          } else if (sscanf(args[i], "%hu", &port) == 1) {
115
-            addr.sin_family = AF_INET;
116
-            addr.sin_port = htons(port);
117
-            addr.sin_addr.s_addr = htonl(INADDR_ANY);
118
-            if (bind(udpSocket, (struct sockaddr *)&addr, sizeof(addr)) != 0)
145
+          } else {
146
+            if (!txt2addr6(args[i], &addr6) ||
147
+                bind(udpSocket, (struct sockaddr *)&addr6, sizeof(addr6)) != 0)
119 148
               printf("could not set source address to \"%s\"\n", args[i]);
120
-          } else
121
-            printf("invalid source address \"%s\"\n", args[i]);
149
+          }
122 150
         } else
123 151
           printf("missing source address for \"-s\"\n");
124 152
       }
... ...
@@ -126,28 +154,23 @@ int main(int argCnt, char **args)
126 154
       else if (strcmp(args[i], "-d") == 0) {
127 155
         if (i + 1 < argCnt) {
128 156
           i++;
129
-          if (sscanf(args[i], "%32[0-9.]:%hu", txt, &port) == 2) {
130
-            addr.sin_family = AF_INET;
131
-            addr.sin_port = htons(port);
132
-            addr.sin_addr.s_addr = inet_addr(txt);
133
-            if (connect(udpSocket, (struct sockaddr *)&addr, sizeof(addr)) !=
134
-                0)
157
+          if (!ipv6) {
158
+            if (!txt2addr(args[i], &addr) ||
159
+                connect(udpSocket, (struct sockaddr *)&addr,
160
+                        sizeof(addr)) != 0)
135 161
                 printf("could not set destination address to \"%s\"\n",
136 162
                        args[i]);
137 163
             else
138 164
               connected = 1;
139
-          } else if (sscanf(args[i], "%32[0-9.]", txt) == 1) {
140
-            addr.sin_family = AF_INET;
141
-            addr.sin_port = htons(2323);
142
-            addr.sin_addr.s_addr = inet_addr(txt);
143
-            if (connect(udpSocket, (struct sockaddr *)&addr, sizeof(addr)) !=
144
-                0)
165
+          } else {
166
+            if (!txt2addr6(args[i], &addr6) ||
167
+                connect(udpSocket, (struct sockaddr *)&addr6,
168
+                        sizeof(addr6)) != 0)
145 169
                 printf("could not set destination address to \"%s\"\n",
146 170
                        args[i]);
147 171
             else
148 172
               connected = 1;
149
-          } else
150
-            printf("invalid destination address \"%s\"\n", args[i]);
173
+          }
151 174
         } else
152 175
           printf("missing destination address for \"-d\"\n");
153 176
       }
... ...
@@ -194,18 +217,27 @@ int main(int argCnt, char **args)
194 217
           i++;
195 218
           if (!connected)       // try to connect if not yet connected
196 219
           {
220
+            if (!ipv6) {
197 221
               printf("no destination address to sent movie \"%s\" to,\n"
198 222
                      "  using default destination address \"127.0.0.1:2323\"\n",
199 223
                      args[i]);
200
-            addr.sin_family = AF_INET;
201
-            addr.sin_port = htons(2323);
202
-            addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
203
-            if (connect(udpSocket, (struct sockaddr *)&addr, sizeof(addr)) !=
204
-                0)
205
-              printf
206
-                  ("could not set destination address to \"127.0.0.1:2323\"\n");
224
+              if (!txt2addr("127.0.0.1:2323", &addr) ||
225
+                  connect(udpSocket, (struct sockaddr *)&addr,
226
+                          sizeof(addr)) != 0)
227
+                printf("could not set destination address to \"127.0.0.1:2323\"\n");
207 228
               else
208 229
                 connected = 1;
230
+            } else {
231
+              printf("no destination address to sent movie \"%s\" to,\n"
232
+                     "  using default destination address \"[::1]:2323\"\n",
233
+                     args[i]);
234
+              if (!txt2addr6("[::1]:2323", &addr6) ||
235
+                  connect(udpSocket, (struct sockaddr *)&addr6,
236
+                          sizeof(addr6)) != 0)
237
+                printf("could not set destination address to \"[::1]:2323\"\n");
238
+              else
239
+                connected = 1;
240
+            }
209 241
           }
210 242
           if (connected) {
211 243
             pMovie = BlinkenMovieLoad(args[i]);
... ...
@@ -4,7 +4,7 @@
4 4
 # a blinkenarea.org project
5 5
 
6 6
 CC=gcc
7
-CFLAGS=-W -Wall -fPIC -O2 -I..
7
+CFLAGS=-Wall -Wextra -Werror -fPIC -O2 -I..
8 8
 LFLAGS=-L.
9 9
 AR=ar
10 10
 RANLIB=ranlib
... ...
@@ -71,23 +71,26 @@ libBlinkenLib.$(SHLIBEXT): libBlinkenLib.$(SHLIBEXT).$(VERSION_MAJOR)
71 71
 	rm -f $@
72 72
 	ln -s $< $@
73 73
 
74
+Tools2.o: Tools2.c Tools2.h
75
+	$(CC) $(CFLAGS) -c -o $@ $<
76
+
74 77
 BlinkenConv.o: BlinkenConv.c BlinkenLib.h config.h BlinkenColorizer.h BlinkenProto.h BlinkenFrame.h BlinkenMovie.h
75 78
 	$(CC) $(CFLAGS) -c -o $@ $<
76 79
 
77 80
 BlinkenConv: BlinkenConv.o libBlinkenLib.$(SHLIBEXT)
78 81
 	$(CC) $(LFLAGS) -o $@ $< -lBlinkenLib
79 82
 
80
-BlinkenSend.o: BlinkenSend.c BlinkenLib.h config.h BlinkenColorizer.h BlinkenProto.h BlinkenFrame.h BlinkenMovie.h
83
+BlinkenSend.o: BlinkenSend.c BlinkenLib.h config.h BlinkenColorizer.h BlinkenProto.h BlinkenFrame.h BlinkenMovie.h Tools2.h
81 84
 	$(CC) $(CFLAGS) -c -o $@ $<
82 85
 
83
-BlinkenSend: BlinkenSend.o libBlinkenLib.$(SHLIBEXT)
84
-	$(CC) $(LFLAGS) -o $@ $< -lBlinkenLib
86
+BlinkenSend: BlinkenSend.o Tools2.o libBlinkenLib.$(SHLIBEXT)
87
+	$(CC) $(LFLAGS) -o $@ $(filter %.o,$^) -lBlinkenLib
85 88
 
86
-BlinkenRecv.o: BlinkenRecv.c BlinkenLib.h config.h BlinkenColorizer.h BlinkenProto.h BlinkenFrame.h BlinkenMovie.h
89
+BlinkenRecv.o: BlinkenRecv.c BlinkenLib.h config.h BlinkenColorizer.h BlinkenProto.h BlinkenFrame.h BlinkenMovie.h Tools2.h
87 90
 	$(CC) $(CFLAGS) -c -o $@ $<
88 91
 
89
-BlinkenRecv: BlinkenRecv.o libBlinkenLib.$(SHLIBEXT)
90
-	$(CC) $(LFLAGS) -o $@ $< -lBlinkenLib
92
+BlinkenRecv: BlinkenRecv.o Tools2.o libBlinkenLib.$(SHLIBEXT)
93
+	$(CC) $(LFLAGS) -o $@ $(filter %.o,$^) -lBlinkenLib
91 94
 
92 95
 BlinkenOutput.o: BlinkenOutput.c BlinkenLib.h config.h BlinkenColorizer.h BlinkenProto.h BlinkenFrame.h BlinkenMovie.h
93 96
 	$(CC) $(CFLAGS) -c -o $@ $<
... ...
@@ -0,0 +1,77 @@
1
+/* BlinkenLib
2
+   Copyright 2004-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 <stdio.h>
7
+#include <stdlib.h>
8
+#include <string.h>
9
+#ifdef WIN32
10
+#include <winsock2.h>
11
+#else
12
+#include <sys/types.h>
13
+#include <sys/socket.h>
14
+#include <netinet/in.h>
15
+#include <arpa/inet.h>
16
+#endif
17
+
18
+#include "Tools2.h"
19
+
20
+// convert text to IPv4 address
21
+int txt2addr(char *text, struct sockaddr_in *addr)
22
+{
23
+  char txt[48];
24
+  unsigned short port;
25
+
26
+  if (sscanf(text, "%32[0-9.]:%hu", txt, &port) == 2) {
27
+    addr->sin_family = AF_INET;
28
+    addr->sin_port = htons(port);
29
+    addr->sin_addr.s_addr = inet_addr(txt);
30
+    return 1;
31
+  } else if (sscanf(text, "%32[0-9.]", txt) == 1) {
32
+    addr->sin_family = AF_INET;
33
+    addr->sin_port = htons(2323);
34
+    addr->sin_addr.s_addr = inet_addr(txt);
35
+    return 1;
36
+  } else if (sscanf(text, "%hu", &port) == 1) {
37
+    addr->sin_family = AF_INET;
38
+    addr->sin_port = htons(port);
39
+    addr->sin_addr.s_addr = htonl(INADDR_ANY);
40
+    return 1;
41
+  } else {
42
+    return 0;
43
+  }
44
+}
45
+
46
+// convert text to IPv6 address
47
+int txt2addr6(char *text, struct sockaddr_in6 *addr6)
48
+{
49
+  char txt[128];
50
+  unsigned short port;
51
+
52
+  if (sscanf(text, "[%96[0-9a-fA-F:]]:%hu", txt, &port) == 2) {
53
+    addr6->sin6_family = AF_INET6;
54
+    addr6->sin6_port = htons(port);
55
+    if (inet_pton(AF_INET6, txt, &addr6->sin6_addr))
56
+      return 1;
57
+    else
58
+      return 0;
59
+  } else if (sscanf(text, "[%96[0-9a-fA-F:]]", txt) == 1) {
60
+    addr6->sin6_family = AF_INET6;
61
+    addr6->sin6_port = htons(2323);
62
+    if (inet_pton(AF_INET6, txt, &addr6->sin6_addr))
63
+      return 1;
64
+    else
65
+      return 0;
66
+  } else if (sscanf(text, "%hu", &port) == 1) {
67
+    addr6->sin6_family = AF_INET6;
68
+    addr6->sin6_port = htons(port);
69
+    if (inet_pton(AF_INET6, "::", &addr6->sin6_addr))
70
+      return 1;
71
+    else
72
+      return 0;
73
+  } else {
74
+    return 0;
75
+  }
76
+}
77
+
... ...
@@ -0,0 +1,22 @@
1
+/* BlinkenLib
2
+   Copyright 2004-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 INC_BlinkenLib_Tools2
7
+#define INC_BlinkenLib_Tools2
8
+
9
+#ifdef WIN32
10
+#include <winsock2.h>
11
+#else
12
+#include <arpa/inet.h>
13
+#endif
14
+
15
+// convert text to IPv4 address
16
+int txt2addr(char *text, struct sockaddr_in *addr);
17
+
18
+// convert text to IPv6 address
19
+int txt2addr6(char *text, struct sockaddr_in6 *addr6);
20
+
21
+#endif // #ifndef INC_BlinkenLib_Tools2
22
+
... ...
@@ -1,3 +1,7 @@
1
+0.7.4 2014-01-02
2
+----------------
3
+add IPv6 support to BlinkenSend and BlinkenRecv
4
+
1 5
 0.7.3 2013-12-28
2 6
 ----------------
3 7
 more baud rates for BlinkenOutput
... ...
@@ -1,5 +1,5 @@
1 1
 VERSION_MAJOR=0
2 2
 VERSION_MINOR=7
3
-VERSION_REVISION=2
3
+VERSION_REVISION=4
4 4
 VERSION=$(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_REVISION)
5 5
 
6 6