| 307 | } |
| 308 | |
| 309 | bool control_conn_t::process_start_stop(cp_cmd pktType) |
| 310 | { |
| 311 | using std::string; |
| 312 | |
| 313 | constexpr int pkt_size = 2 + sizeof(handle_t); |
| 314 | |
| 315 | if (rbuf.get_length() < pkt_size) { |
| 316 | chklen = pkt_size; |
| 317 | return true; |
| 318 | } |
| 319 | |
| 320 | // 1 byte: packet type |
| 321 | // 1 byte: flags |
| 322 | // bit 0: 0 = no pin, 1 = pin |
| 323 | // bit 1: 0 = force stop, 1 = not forced ("gentle") |
| 324 | // bit 2: 0 = don't restart, 1 = restart after stopping |
| 325 | // --- (reserved) |
| 326 | // bit 7: 0 = no pre-ack, 1 = issue pre-ack |
| 327 | // 4 bytes: service handle |
| 328 | |
| 329 | bool do_pin = ((rbuf[1] & 1) == 1); |
| 330 | handle_t handle; |
| 331 | rbuf.extract((char *) &handle, 2, sizeof(handle)); |
| 332 | |
| 333 | service_record *service = find_service_for_key(handle); |
| 334 | if (service == nullptr) { |
| 335 | // Service handle is bad |
| 336 | char badreqRep[] = { (char)cp_rply::BADREQ }; |
| 337 | if (!queue_packet(badreqRep, 1)) return false; |
| 338 | bad_conn_close = true; |
| 339 | return true; |
| 340 | } |
| 341 | else { |
| 342 | char ack_buf[1] = { (char)cp_rply::PREACK }; |
| 343 | if (rbuf[1] & 128) { |
| 344 | // Issue PREACK before doing anything that might change service state (and cause a |
| 345 | // service event info packet to be issued as a result). This allows the client to |
| 346 | // determine whether the info packets were queued before or after the command was |
| 347 | // processed. |
| 348 | if (!queue_packet(ack_buf, 1)) return false; |
| 349 | } |
| 350 | |
| 351 | ack_buf[0] = (char)cp_rply::ACK; |
| 352 | |
| 353 | switch (pktType) { |
| 354 | case cp_cmd::STARTSERVICE: |
| 355 | // start service, mark as required |
| 356 | if (services->is_shutting_down()) { |
| 357 | ack_buf[0] = (char)cp_rply::SHUTTINGDOWN; |
| 358 | break; |
| 359 | } |
| 360 | if ((service->get_state() == service_state_t::STOPPED |
| 361 | || service->get_state() == service_state_t::STOPPING) |
| 362 | && service->is_stop_pinned()) { |
| 363 | ack_buf[0] = (char)cp_rply::PINNEDSTOPPED; |
| 364 | break; |
| 365 | } |
| 366 | if (do_pin) service->pin_start(); |
nothing calls this directly
no test coverage detected