19
19
#include < string.h>
20
20
#include " mbed.h"
21
21
22
- static bool address_is_ipv4 (const char *addr)
22
+
23
+ static bool ipv4_is_valid (const char *addr)
23
24
{
24
25
int i = 0 ;
25
26
@@ -38,7 +39,7 @@ static bool address_is_ipv4(const char *addr)
38
39
return true ;
39
40
}
40
41
41
- static bool address_is_ipv6 (const char *addr)
42
+ static bool ipv6_is_valid (const char *addr)
42
43
{
43
44
// Check each digit for [0-9a-fA-F:]
44
45
for (int i = 0 ; addr[i]; i++) {
@@ -53,20 +54,57 @@ static bool address_is_ipv6(const char *addr)
53
54
return true ;
54
55
}
55
56
56
- static void address_to_ipv4 (uint8_t *bytes, const char *addr)
57
+ static void ipv4_from_address (uint8_t *bytes, const char *addr)
57
58
{
58
- sscanf (addr, " %hhd.%hhd.%hhd.%hhd" , &bytes[0 ], &bytes[1 ], &bytes[2 ], &bytes[3 ]);
59
+ sscanf (addr, " %hhu.%hhu.%hhu.%hhu" , &bytes[0 ], &bytes[1 ], &bytes[2 ], &bytes[3 ]);
60
+ }
61
+
62
+ static int ipv6_scan_chunk (uint16_t *shorts, const char *chunk) {
63
+ int count = 0 ;
64
+ int i = 0 ;
65
+
66
+ for (; count < NSAPI_IPv6_BYTES/2 ; count++) {
67
+ int scanned = sscanf (&chunk[i], " %hx" , &shorts[count]);
68
+ if (scanned < 1 ) {
69
+ return count;
70
+ }
71
+
72
+ for (; chunk[i] != ' :' ; i++) {
73
+ if (!chunk[i]) {
74
+ return count+1 ;
75
+ }
76
+ }
77
+
78
+ i++;
79
+ }
80
+
81
+ return count;
59
82
}
60
83
61
- static void address_to_ipv6 (uint8_t *bytes, const char *addr)
84
+ static void ipv6_from_address (uint8_t *bytes, const char *addr)
62
85
{
63
- // TODO support short form (::1, 2001::ffee:100a)
64
- // Use a more intellegent algorithm
86
+ // Start with zeroed address
65
87
uint16_t shorts[NSAPI_IPv6_BYTES/2 ];
66
- sscanf (addr, " %hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx" ,
67
- &shorts[0 ], &shorts[1 ], &shorts[2 ], &shorts[3 ],
68
- &shorts[4 ], &shorts[5 ], &shorts[6 ], &shorts[7 ]);
88
+ memset (shorts, 0 , sizeof shorts);
69
89
90
+ int suffix = 0 ;
91
+
92
+ // Find double colons and scan suffix
93
+ for (int i = 0 ; addr[i]; i++) {
94
+ if (addr[i] == ' :' && addr[i+1 ] == ' :' ) {
95
+ suffix = ipv6_scan_chunk (shorts, &addr[i+2 ]);
96
+ break ;
97
+ }
98
+ }
99
+
100
+ // Move suffix to end
101
+ memmove (&shorts[NSAPI_IPv6_BYTES/2 -suffix], &shorts[0 ],
102
+ suffix*sizeof (uint16_t ));
103
+
104
+ // Scan prefix
105
+ ipv6_scan_chunk (shorts, &addr[0 ]);
106
+
107
+ // Flip bytes
70
108
for (int i = 0 ; i < NSAPI_IPv6_BYTES/2 ; i++) {
71
109
bytes[2 *i+0 ] = (uint8_t )(shorts[i] >> 8 );
72
110
bytes[2 *i+1 ] = (uint8_t )(shorts[i] >> 0 );
@@ -80,31 +118,23 @@ static void ipv4_to_address(char *addr, const uint8_t *bytes)
80
118
81
119
static void ipv6_to_address (char *addr, const uint8_t *bytes)
82
120
{
83
- int pos = 0 ;
84
- for (int i = 0 ; i < NSAPI_IPv6_BYTES; i+=2 ) {
85
- int ret = sprintf (&addr[pos], " %02x%02x" , bytes[i], bytes[i+1 ]);
86
- if (ret < 0 ) {
87
- memset (addr, 0 , NSAPI_IPv6_SIZE + 1 );
88
- return ;
89
- }
90
- pos += ret;
91
-
92
- addr[pos++] = ' :' ;
121
+ for (int i = 0 ; i < NSAPI_IPv6_BYTES/2 ; i++) {
122
+ sprintf (&addr[5 *i], " %02x%02x" , bytes[2 *i], bytes[2 *i+1 ]);
123
+ addr[5 *i+4 ] = ' :' ;
93
124
}
94
- pos -= 1 ; // Overwrite last ':'
95
- addr[pos++] = ' \0 ' ;
96
- MBED_ASSERT (NSAPI_IPv6_SIZE == pos);
125
+ addr[NSAPI_IPv6_SIZE-1 ] = ' \0 ' ;
97
126
}
98
127
128
+
99
129
SocketAddress::SocketAddress (NetworkInterface *iface, const char *host, uint16_t port)
100
130
{
101
131
// Check for valid IP addresses
102
- if (host && address_is_ipv4 (host)) {
132
+ if (host && ipv4_is_valid (host)) {
103
133
_ip_version = NSAPI_IPv4;
104
- address_to_ipv4 (_ip_bytes, host);
105
- } else if (host && address_is_ipv6 (host)) {
134
+ ipv4_from_address (_ip_bytes, host);
135
+ } else if (host && ipv6_is_valid (host)) {
106
136
_ip_version = NSAPI_IPv6;
107
- address_to_ipv4 (_ip_bytes, host);
137
+ ipv4_from_address (_ip_bytes, host);
108
138
} else {
109
139
// DNS lookup
110
140
int err = iface->gethostbyname (this , host);
@@ -140,12 +170,12 @@ void SocketAddress::set_ip_address(const char *addr)
140
170
{
141
171
_ip_address[0 ] = ' \0 ' ;
142
172
143
- if (addr && address_is_ipv4 (addr)) {
173
+ if (addr && ipv4_is_valid (addr)) {
144
174
_ip_version = NSAPI_IPv4;
145
- address_to_ipv4 (_ip_bytes, addr);
146
- } else if (addr && address_is_ipv6 (addr)) {
175
+ ipv4_from_address (_ip_bytes, addr);
176
+ } else if (addr && ipv6_is_valid (addr)) {
147
177
_ip_version = NSAPI_IPv6;
148
- address_to_ipv6 (_ip_bytes, addr);
178
+ ipv6_from_address (_ip_bytes, addr);
149
179
} else {
150
180
_ip_version = NSAPI_IPv4;
151
181
memset (_ip_bytes, 0 , NSAPI_IPv4_BYTES);
0 commit comments