Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / native_client_sdk / src / libraries / nacl_io / syscalls / socket / inet_ntop.cc
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "nacl_io/ossocket.h"
6 #if defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) && !defined(__BIONIC__)
7
8 #include <errno.h>
9 #include <string.h>
10
11 #include <iostream>
12 #include <sstream>
13 #include <string>
14
15 #include "sdk_util/macros.h"
16
17 EXTERN_C_BEGIN
18
19 const char* inet_ntop(int af, const void* src, char* dst, socklen_t size) {
20   if (AF_INET == af) {
21     if (size < INET_ADDRSTRLEN) {
22       errno = ENOSPC;
23       return NULL;
24     }
25     struct in_addr in;
26     memcpy(&in, src, sizeof(in));
27     char* result = inet_ntoa(in);
28     memcpy(dst, result, strlen(result) + 1);
29     return dst;
30   }
31
32   if (AF_INET6 == af) {
33     if (size < INET6_ADDRSTRLEN) {
34       errno = ENOSPC;
35       return NULL;
36     }
37
38     // Convert to an array of 8 host order shorts
39     const uint16_t* tuples = static_cast<const uint16_t*>(src);
40     uint16_t host_tuples[8];
41     int zero_run_start = -1;
42     int zero_run_end = -1;
43     for (int i = 0; i < 8; i++) {
44       host_tuples[i] = ntohs(tuples[i]);
45       if (host_tuples[i] == 0) {
46         if (zero_run_start == -1)
47           zero_run_start = i;
48       } else if (zero_run_start != -1 && zero_run_end == -1) {
49         zero_run_end = i;
50       }
51     }
52
53     if (zero_run_start != -1) {
54       if (zero_run_end == -1)
55         zero_run_end = 8;
56       if (zero_run_end - zero_run_start < 2) {
57         zero_run_start = -1;
58         zero_run_end = -1;
59       }
60     }
61
62     // Mimick glibc's behaviour here and allow ipv4 address to be specified
63     // as either ::A.B.C.D or ::ffff:A.B.C.D.
64     if (zero_run_start == 0 &&
65         (zero_run_end == 6 ||
66          (zero_run_end == 5 && host_tuples[zero_run_end] == 0xffff))) {
67       if (zero_run_end == 5) {
68         strcpy(dst, "::ffff:");
69       } else {
70         strcpy(dst, "::");
71       }
72       inet_ntop(AF_INET, host_tuples + 6, dst + strlen(dst), INET_ADDRSTRLEN);
73     } else {
74       std::stringstream output;
75       for (int i = 0; i < 8; i++) {
76         if (i == zero_run_start) {
77           output << "::";
78           continue;
79         }
80         if (i > zero_run_start && i < zero_run_end)
81           continue;
82         output << std::hex << host_tuples[i];
83         if (i < 7 && i + 1 != zero_run_start)
84           output << ":";
85       }
86       memcpy(dst, output.str().c_str(), output.str().size() + 1);
87     }
88     return dst;
89   }
90
91   errno = EAFNOSUPPORT;
92   return NULL;
93 }
94
95 EXTERN_C_END
96
97 #endif  // defined(PROVIDES_SOCKET_API) && !defined(__GLIBC__) ...