]> git.armaanb.net Git - gen-shell.git/blob - src/libshared/src/ip.cpp
added install instructions
[gen-shell.git] / src / libshared / src / ip.cpp
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright 2006 - 2017, Paul Beckingham, Federico Hernandez.
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining a copy
6 // of this software and associated documentation files (the "Software"), to deal
7 // in the Software without restriction, including without limitation the rights
8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 // copies of the Software, and to permit persons to whom the Software is
10 // furnished to do so, subject to the following conditions:
11 //
12 // The above copyright notice and this permission notice shall be included
13 // in all copies or substantial portions of the Software.
14 //
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 // SOFTWARE.
22 //
23 // http://www.opensource.org/licenses/mit-license.php
24 //
25 ////////////////////////////////////////////////////////////////////////////////
26
27 #include <cmake.h>
28 #include <shared.h>
29 #include <cctype>
30
31 static bool isPort (const std::string&, unsigned int&);
32 static bool isChar (const std::string&, char, unsigned int&);
33 static bool isEOS (const std::string&, unsigned int&);
34 static bool isIPv4Block (const std::string&, unsigned int&);
35 static bool isIPv4BlockSet (const std::string&, unsigned int&);
36 static bool isIPv6Block (const std::string&, unsigned int&);
37 static bool isIPv6BlockSet (const std::string&, unsigned int&);
38
39 ////////////////////////////////////////////////////////////////////////////////
40 static bool isPort (const std::string& input, unsigned int& c)
41 {
42   auto start = c;
43   while (std::isdigit (input[c]))
44     ++c;
45
46   return c - start > 0 &&
47          c - start < 6;
48 }
49
50 ////////////////////////////////////////////////////////////////////////////////
51 static bool isChar (const std::string& input, char character, unsigned int& c)
52 {
53   if (input[c] == character)
54   {
55     ++c;
56     return true;
57   }
58
59   return false;
60 }
61
62 ////////////////////////////////////////////////////////////////////////////////
63 static bool isEOS (const std::string& input, unsigned int& c)
64 {
65   return c >= input.length ();
66 }
67
68 ////////////////////////////////////////////////////////////////////////////////
69 static bool isIPv4Block (const std::string& input, unsigned int& c)
70 {
71   auto start = c;
72   while (std::isdigit (input[c]))
73     ++c;
74
75   if (c - start > 0 &&
76       c - start < 4)
77   {
78     auto byte = std::stoi (input.substr (start, c - start));
79     if (byte < 256)
80       return true;
81   }
82
83   c = start;
84   return false;
85 }
86
87 ////////////////////////////////////////////////////////////////////////////////
88 static bool isIPv4BlockSet (const std::string& input, unsigned int& c)
89 {
90   auto start = c;
91
92   if (isIPv4Block (input,      c) &&
93       isChar      (input, '.', c) &&
94       isIPv4Block (input,      c) &&
95       isChar      (input, '.', c) &&
96       isIPv4Block (input,      c) &&
97       isChar      (input, '.', c) &&
98       isIPv4Block (input,      c))
99   {
100
101     return true;
102   }
103
104   c = start;
105   return false;
106 }
107
108 ////////////////////////////////////////////////////////////////////////////////
109 static bool isIPv6Block (const std::string& input, unsigned int& c)
110 {
111   auto start = c;
112   while (std::isxdigit (input[c]))
113     ++c;
114
115   if (c - start > 0 &&
116       c - start < 5)
117   {
118     return true;
119   }
120
121   c = start;
122   return false;
123 }
124
125 ////////////////////////////////////////////////////////////////////////////////
126 // at least one non-empty block, or '::'
127 // at least two colons
128 // 8 or less blocks
129 static bool isIPv6BlockSet (const std::string& input, unsigned int& c)
130 {
131   auto start = c;
132   int count_colons {0};
133   int count_blocks {0};
134
135   while (1)
136   {
137     if (isEOS (input, c))
138     {
139       if (c == start)
140         return false;
141
142       break;
143     }
144
145     else if (isChar (input, ':', c))
146       ++count_colons;
147
148     else if (isIPv4BlockSet (input, c))
149       ++count_blocks;
150
151     else if (isIPv6Block (input, c))
152       ++count_blocks;
153
154     else if (isChar (input, '.', c) ||
155              isChar (input, ']', c))
156     {
157       --c;
158       break;
159     }
160
161     else
162       break;
163   }
164
165   if (count_colons >= 2 &&
166       count_colons <= 7 &&
167       ((count_blocks == 0 && input.substr (start, c) == "::") || count_blocks >= 1) &&
168       count_blocks <= 8)
169   {
170     return true;
171   }
172
173   c = start;
174   return false;
175 }
176
177 ////////////////////////////////////////////////////////////////////////////////
178 // <address>:<port>
179 // <address>
180 bool isIPv4Address (const std::string& input, std::string& address, int& port)
181 {
182   unsigned int c = 0;
183   if (isIPv4BlockSet (input, c))
184   {
185     auto colon = c;
186     if (isChar (input, ':', c))
187       if (! isPort (input, c))
188         return false;
189
190     if (isEOS (input, c))
191     {
192       address = input.substr (0, std::min (c, colon));
193       if (! isEOS (input, colon))
194         port = std::stoi (input.substr (colon + 1));
195
196       return true;
197     }
198   }
199
200   return false;
201 }
202
203 ////////////////////////////////////////////////////////////////////////////////
204 //  [<address>]:<port>
205 //  <address>
206 bool isIPv6Address (const std::string& input, std::string& address, int& port)
207 {
208   unsigned int c = 0;
209
210   if (isChar         (input, '[', c) &&
211       isIPv6BlockSet (input,      c) &&
212       isChar         (input, ']', c))
213   {
214     auto colon = c;
215     if (isChar         (input, ':', c) &&
216         isPort         (input,      c) &&
217         isEOS          (input,      c))
218     {
219       address = input.substr (1, colon - 2);
220       port = std::stoi (input.substr (colon + 1));
221       return true;
222     }
223   }
224
225   c = 0;
226   if (isIPv6BlockSet (input, c) &&
227       isEOS          (input, c))
228   {
229     address = input;
230     port = 0;
231     return true;
232   }
233
234   return false;
235 }
236
237 ////////////////////////////////////////////////////////////////////////////////