btrfs: Attempt to fix GCC2 build.
[haiku.git] / src / add-ons / kernel / network / dns_resolver / server / main.cpp
blobca898ecbcfc0ed9b82c9cbff1ef373f274e46b9f
1 /*
2 * Copyright 2012 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Paweł Dziepak, pdziepak@quarnos.org
7 */
10 #include <stdlib.h>
11 #include <string.h>
13 #include <sys/socket.h>
14 #include <netdb.h>
16 #include <AutoDeleter.h>
17 #include <OS.h>
18 #include <SupportDefs.h>
20 #include "Definitions.h"
23 port_id gRequestPort;
24 port_id gReplyPort;
27 status_t
28 Serialize(char** _reply, uint32* _totalSize, const struct addrinfo* ai)
30 uint32 addrsSize = ai == NULL ? 0 : sizeof(addrinfo);
31 uint32 namesSize = 0;
32 uint32 socksSize = 0;
34 const struct addrinfo* current = ai;
35 while (current != NULL) {
36 if (current->ai_canonname != NULL)
37 namesSize += strlen(current->ai_canonname) + 1;
38 if (current->ai_addr != NULL) {
39 if (current->ai_family == AF_INET)
40 socksSize += sizeof(sockaddr_in);
41 else
42 socksSize += sizeof(sockaddr_in6);
44 if (current->ai_next != NULL)
45 addrsSize += sizeof(addrinfo);
46 current = current->ai_next;
49 uint32 totalSize = addrsSize + namesSize + socksSize;
50 char* reply = reinterpret_cast<char*>(malloc(totalSize));
51 if (reply == NULL)
52 return B_NO_MEMORY;
54 uint32 addrPos = 0;
55 uint32 namePos = addrsSize;
56 uint32 sockPos = addrsSize + namesSize;
58 struct addrinfo temp;
60 current = ai;
61 while (current != NULL) {
62 memcpy(&temp, current, sizeof(addrinfo));
64 if (current->ai_canonname != NULL) {
65 strcpy(reply + namePos, current->ai_canonname);
66 uint32 nSize = strlen(current->ai_canonname) + 1;
67 temp.ai_canonname = reinterpret_cast<char*>(namePos);
68 namePos += nSize;
70 if (current->ai_addr != NULL) {
71 if (current->ai_family == AF_INET) {
72 memcpy(reply + sockPos, current->ai_addr, sizeof(sockaddr_in));
73 temp.ai_addr = reinterpret_cast<sockaddr*>(sockPos);
74 sockPos += sizeof(sockaddr_in);
75 } else {
76 memcpy(reply + sockPos, current->ai_addr, sizeof(sockaddr_in6));
77 temp.ai_addr = reinterpret_cast<sockaddr*>(sockPos);
78 sockPos += sizeof(sockaddr_in6);
82 addrinfo* next = current->ai_next;
83 if (next != NULL)
84 temp.ai_next = reinterpret_cast<addrinfo*>(addrPos) + 1;
85 else
86 temp.ai_next = NULL;
88 memcpy(reply + addrPos, &temp, sizeof(addrinfo));
89 addrPos += sizeof(addrinfo);
91 current = next;
94 *_reply = reply;
95 *_totalSize = totalSize;
96 return B_OK;
100 status_t
101 GetAddrInfo(const char* buffer)
103 const char* node = buffer[0] == '\0' ? NULL : buffer;
104 uint32 nodeSize = node != NULL ? strlen(node) + 1 : 1;
106 const char* service = buffer[nodeSize] == '\0' ? NULL : buffer + nodeSize;
107 uint32 serviceSize = service != NULL ? strlen(service) + 1 : 1;
109 const struct addrinfo* hints
110 = reinterpret_cast<const addrinfo*>(buffer + nodeSize + serviceSize);
112 struct addrinfo* ai;
113 status_t result = getaddrinfo(node, service, hints, &ai);
114 if (result != B_OK)
115 return write_port(gReplyPort, MsgError, &result, sizeof(result));
117 uint32 totalSize;
118 char* reply;
119 result = Serialize(&reply, &totalSize, ai);
120 freeaddrinfo(ai);
121 if (result != B_OK)
122 return write_port(gReplyPort, MsgError, &result, sizeof(result));
123 return write_port(gReplyPort, MsgReply, reply, totalSize);
127 status_t
128 MainLoop()
130 do {
131 ssize_t size = port_buffer_size(gRequestPort);
132 if (size < B_OK)
133 return 0;
135 void* buffer = malloc(size);
136 if (buffer == NULL)
137 return B_NO_MEMORY;
138 MemoryDeleter _(buffer);
140 int32 code;
141 size = read_port(gRequestPort, &code, buffer, size);
142 if (size < B_OK)
143 return 0;
145 status_t result;
146 switch (code) {
147 case MsgGetAddrInfo:
148 result = GetAddrInfo(reinterpret_cast<char*>(buffer));
149 break;
151 default:
152 result = B_BAD_VALUE;
153 write_port(gReplyPort, MsgError, &result, sizeof(result));
154 result = B_OK;
157 if (result != B_OK)
158 return 0;
159 } while (true);
164 main(int argc, char** argv)
166 gRequestPort = find_port(kPortNameReq);
167 if (gRequestPort < B_OK) {
168 fprintf(stderr, "%s\n", strerror(gRequestPort));
169 return gRequestPort;
172 gReplyPort = find_port(kPortNameRpl);
173 if (gReplyPort < B_OK) {
174 fprintf(stderr, "%s\n", strerror(gReplyPort));
175 return gReplyPort;
178 return MainLoop();