1 /* 2 * Copyright 2006, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Axel Dörfler, axeld@pinc-software.de 7 */ 8 9 10 #include "Services.h" 11 #include "NetServer.h" 12 #include "Settings.h" 13 14 #include <Autolock.h> 15 16 #include <errno.h> 17 #include <netdb.h> 18 #include <netinet/in.h> 19 #include <new> 20 #include <sys/ioctl.h> 21 #include <sys/socket.h> 22 #include <vector> 23 24 using namespace std; 25 26 struct service_address { 27 struct service *owner; 28 int socket; 29 int family; 30 int type; 31 int protocol; 32 sockaddr address; 33 }; 34 35 typedef vector<service_address> AddressList; 36 37 struct service { 38 std::string name; 39 std::string launch; 40 uid_t user; 41 gid_t group; 42 AddressList addresses; 43 44 ~service(); 45 bool operator!=(const struct service& other); 46 bool operator==(const struct service& other); 47 }; 48 49 50 int 51 parse_type(const char* string) 52 { 53 if (!strcasecmp(string, "stream")) 54 return SOCK_STREAM; 55 56 return SOCK_DGRAM; 57 } 58 59 60 int 61 parse_protocol(const char* string) 62 { 63 struct protoent* proto = getprotobyname(string); 64 if (proto == NULL) 65 return IPPROTO_TCP; 66 67 return proto->p_proto; 68 } 69 70 71 int 72 type_for_protocol(int protocol) 73 { 74 // default determined by protocol 75 switch (protocol) { 76 case IPPROTO_TCP: 77 return SOCK_STREAM; 78 79 case IPPROTO_UDP: 80 default: 81 return SOCK_DGRAM; 82 } 83 } 84 85 86 // #pragma mark - 87 88 89 service::~service() 90 { 91 // close all open sockets 92 AddressList::const_iterator iterator = addresses.begin(); 93 for (; iterator != addresses.end(); iterator++) { 94 const service_address& address = *iterator; 95 96 close(address.socket); 97 } 98 } 99 100 101 bool 102 service::operator!=(const struct service& other) 103 { 104 return !(*this == other); 105 } 106 107 108 bool 109 service::operator==(const struct service& other) 110 { 111 if (name != other.name 112 || launch != other.launch) 113 return false; 114 115 // TODO: compare addresses! 116 return true; 117 } 118 119 120 // #pragma mark - 121 122 123 Services::Services(const BMessage& services) 124 : 125 fListener(-1), 126 fUpdate(0), 127 fMaxSocket(0) 128 { 129 _Update(services); 130 131 // setup pipe to communicate with the listener thread - as the listener 132 // blocks on select(), we need a mechanism to interrupt it 133 if (pipe(&fReadPipe) < 0) { 134 fReadPipe = -1; 135 return; 136 } 137 138 fcntl(fReadPipe, F_SETFD, FD_CLOEXEC); 139 fcntl(fWritePipe, F_SETFD, FD_CLOEXEC); 140 141 FD_ZERO(&fSet); 142 FD_SET(fReadPipe, &fSet); 143 144 fMinSocket = fWritePipe + 1; 145 fMaxSocket = fWritePipe + 1; 146 147 fListener = spawn_thread(_Listener, "services listener", B_NORMAL_PRIORITY, this); 148 if (fListener >= B_OK) 149 resume_thread(fListener); 150 } 151 152 153 Services::~Services() 154 { 155 wait_for_thread(fListener, NULL); 156 } 157 158 159 status_t 160 Services::InitCheck() const 161 { 162 return fListener >= B_OK ? B_OK : fListener; 163 } 164 165 166 void 167 Services::MessageReceived(BMessage* message) 168 { 169 switch (message->what) { 170 case kMsgUpdateServices: 171 _Update(*message); 172 break; 173 174 default: 175 BHandler::MessageReceived(message); 176 } 177 } 178 179 180 void 181 Services::_NotifyListener(bool quit) 182 { 183 write(fWritePipe, quit ? "q" : "u", 1); 184 } 185 186 187 void 188 Services::_UpdateMinMaxSocket(int socket) 189 { 190 if (socket >= fMaxSocket) 191 fMaxSocket = socket + 1; 192 if (socket < fMinSocket) 193 fMinSocket = socket; 194 } 195 196 197 status_t 198 Services::_StartService(struct service& service) 199 { 200 // create socket 201 202 bool failed = false; 203 AddressList::iterator iterator = service.addresses.begin(); 204 for (; iterator != service.addresses.end(); iterator++) { 205 service_address& address = *iterator; 206 207 address.socket = socket(address.family, address.type, address.protocol); 208 if (address.socket < 0 209 || bind(address.socket, &address.address, address.address.sa_len) < 0 210 || fcntl(address.socket, F_SETFD, FD_CLOEXEC) < 0) { 211 failed = true; 212 break; 213 } 214 215 if (address.type == SOCK_STREAM && listen(address.socket, 50) < 0) { 216 failed = true; 217 break; 218 } 219 } 220 221 if (failed) { 222 // open sockets will be closed when the service is deleted 223 return errno; 224 } 225 226 // add service to maps and activate it 227 228 fNameMap[service.name] = &service; 229 230 iterator = service.addresses.begin(); 231 for (; iterator != service.addresses.end(); iterator++) { 232 service_address& address = *iterator; 233 234 fSocketMap[address.socket] = &address; 235 _UpdateMinMaxSocket(address.socket); 236 FD_SET(address.socket, &fSet); 237 } 238 239 _NotifyListener(); 240 printf("Starting service '%s'\n", service.name.c_str()); 241 return B_OK; 242 } 243 244 245 status_t 246 Services::_StopService(struct service& service) 247 { 248 // remove service from maps 249 { 250 ServiceNameMap::iterator iterator = fNameMap.find(service.name); 251 if (iterator != fNameMap.end()) 252 fNameMap.erase(iterator); 253 } 254 { 255 AddressList::const_iterator iterator = service.addresses.begin(); 256 for (; iterator != service.addresses.end(); iterator++) { 257 const service_address& address = *iterator; 258 259 ServiceSocketMap::iterator socketIterator = fSocketMap.find(address.socket); 260 if (socketIterator != fSocketMap.end()) 261 fSocketMap.erase(socketIterator); 262 263 close(address.socket); 264 FD_CLR(address.socket, &fSet); 265 } 266 } 267 268 delete &service; 269 return B_OK; 270 } 271 272 273 status_t 274 Services::_ToService(const BMessage& message, struct service*& service) 275 { 276 // get mandatory fields 277 const char* name; 278 const char* launch; 279 if (message.FindString("name", &name) != B_OK 280 || message.FindString("launch", &launch) != B_OK) 281 return B_BAD_VALUE; 282 283 service = new (std::nothrow) ::service; 284 if (service == NULL) 285 return B_NO_MEMORY; 286 287 service->name = name; 288 service->launch = launch; 289 290 // TODO: user/group is currently ignored! 291 292 // Default family/port/protocol/type for all addresses 293 294 // we default to inet/tcp/port-from-service-name if nothing is specified 295 const char* string; 296 int32 serviceFamilyIndex; 297 int32 serviceFamily = -1; 298 if (message.FindString("family", &string) != B_OK) 299 string = "inet"; 300 301 if (get_family_index(string, serviceFamilyIndex)) 302 serviceFamily = family_at_index(serviceFamilyIndex); 303 304 int32 serviceProtocol; 305 if (message.FindString("protocol", &string) == B_OK) 306 serviceProtocol = parse_protocol(string); 307 else { 308 string = "tcp"; 309 // we set 'string' here for an eventual call to getservbyname() below 310 serviceProtocol = IPPROTO_TCP; 311 } 312 313 int32 servicePort; 314 if (message.FindInt32("port", &servicePort) != B_OK) { 315 struct servent* servent = getservbyname(name, string); 316 if (servent != NULL) 317 servicePort = servent->s_port; 318 else 319 servicePort = -1; 320 } 321 322 int32 serviceType = -1; 323 if (message.FindString("type", &string) == B_OK) { 324 serviceType = parse_type(string); 325 } else { 326 serviceType = type_for_protocol(serviceProtocol); 327 } 328 329 BMessage address; 330 int32 i = 0; 331 for (; message.FindMessage("address", i, &address) == B_OK; i++) { 332 // TODO: dump problems in the settings to syslog 333 service_address serviceAddress; 334 if (address.FindString("family", &string) != B_OK) 335 continue; 336 337 int32 familyIndex; 338 if (!get_family_index(string, familyIndex)) 339 continue; 340 341 serviceAddress.family = family_at_index(familyIndex); 342 343 if (address.FindString("protocol", &string) == B_OK) 344 serviceAddress.protocol = parse_protocol(string); 345 else 346 serviceAddress.protocol = serviceProtocol; 347 348 if (message.FindString("type", &string) == B_OK) 349 serviceAddress.type = parse_type(string); 350 else if (serviceAddress.protocol != serviceProtocol) 351 serviceAddress.type = type_for_protocol(serviceAddress.protocol); 352 else 353 serviceAddress.type = serviceType; 354 355 if (address.FindString("address", &string) == B_OK) { 356 if (!parse_address(familyIndex, string, serviceAddress.address)) 357 continue; 358 } else 359 set_any_address(familyIndex, serviceAddress.address); 360 361 int32 port; 362 if (address.FindInt32("port", &port) != B_OK) 363 port = servicePort; 364 365 set_port(familyIndex, serviceAddress.address, port); 366 serviceAddress.socket = -1; 367 368 serviceAddress.owner = service; 369 service->addresses.push_back(serviceAddress); 370 } 371 372 if (i == 0 && (serviceFamily < 0 || servicePort < 0)) { 373 // no address specified 374 delete service; 375 return B_BAD_VALUE; 376 } 377 378 if (i == 0) { 379 // no address specified, but family/port were given; add empty address 380 service_address serviceAddress; 381 serviceAddress.family = serviceFamily; 382 serviceAddress.type = serviceType; 383 serviceAddress.protocol = serviceProtocol; 384 385 set_any_address(serviceFamilyIndex, serviceAddress.address); 386 set_port(serviceFamilyIndex, serviceAddress.address, servicePort); 387 serviceAddress.socket = -1; 388 389 serviceAddress.owner = service; 390 service->addresses.push_back(serviceAddress); 391 } 392 393 return B_OK; 394 } 395 396 397 void 398 Services::_Update(const BMessage& services) 399 { 400 BAutolock locker(fLock); 401 fUpdate++; 402 403 BMessage message; 404 for (int32 index = 0; services.FindMessage("service", index, 405 &message) == B_OK; index++) { 406 const char* name; 407 if (message.FindString("name", &name) != B_OK) 408 continue; 409 410 struct service* service; 411 if (_ToService(message, service) != B_OK) 412 continue; 413 414 ServiceNameMap::iterator iterator = fNameMap.find(name); 415 if (iterator == fNameMap.end()) { 416 // this service does not exist yet, start it 417 _StartService(*service); 418 } else { 419 // this service does already exist - check for any changes 420 421 if (service != iterator->second) { 422 _StopService(*iterator->second); 423 _StartService(*service); 424 } 425 } 426 } 427 } 428 429 430 status_t 431 Services::_LaunchService(struct service& service, int socket) 432 { 433 printf("LAUNCH: %s\n", service.launch.c_str()); 434 435 if (fcntl(socket, F_SETFD, 0) < 0) { 436 // could not clear FD_CLOEXEC on socket 437 return errno; 438 } 439 440 pid_t child = fork(); 441 if (child == 0) { 442 setsid(); 443 // make sure we're in our own session, and don't accidently quit the net_server 444 445 // We're the child, replace standard input/output 446 dup2(socket, STDIN_FILENO); 447 dup2(socket, STDOUT_FILENO); 448 dup2(socket, STDERR_FILENO); 449 close(socket); 450 451 // build argument array 452 453 const char** args = (const char**)malloc(2 * sizeof(void *)); 454 if (args == NULL) 455 exit(1); 456 457 args[0] = service.launch.c_str(); 458 args[1] = NULL; 459 if (execv(service.launch.c_str(), (char* const*)args) < 0) 460 exit(1); 461 462 // we'll never trespass here 463 } 464 465 // TODO: make sure child started successfully... 466 return B_OK; 467 } 468 469 470 status_t 471 Services::_Listener() 472 { 473 while (true) { 474 fLock.Lock(); 475 fd_set set = fSet; 476 fLock.Unlock(); 477 478 if (select(fMaxSocket, &set, NULL, NULL, NULL) < 0) { 479 // sleep a bit before trying again 480 snooze(1000000LL); 481 } 482 483 printf("select returned!\n"); 484 if (FD_ISSET(fReadPipe, &set)) { 485 char command; 486 if (read(fReadPipe, &command, 1) == 1 && command == 'q') 487 break; 488 } 489 490 BAutolock locker(fLock); 491 492 for (int i = fMinSocket; i < fMaxSocket; i++) { 493 if (!FD_ISSET(i, &set)) 494 continue; 495 496 ServiceSocketMap::iterator iterator = fSocketMap.find(i); 497 if (iterator == fSocketMap.end()) 498 continue; 499 500 struct service_address& address = *iterator->second; 501 int socket; 502 503 if (address.type == SOCK_STREAM) { 504 // accept incoming connection 505 int value = 1; 506 ioctl(i, FIONBIO, &value); 507 // make sure we don't wait for the connection 508 509 socket = accept(address.socket, NULL, NULL); 510 511 value = 0; 512 ioctl(i, FIONBIO, &value); 513 514 if (socket < 0) 515 continue; 516 } else 517 socket = address.socket; 518 519 // launch this service's handler 520 521 _LaunchService(*address.owner, socket); 522 } 523 } 524 return B_OK; 525 } 526 527 528 /*static*/ status_t 529 Services::_Listener(void* _self) 530 { 531 Services* self = (Services*)_self; 532 return self->_Listener(); 533 } 534