static void inFromChildDecode(struct Admin* admin, struct Admin_Channel* channel) { uint8_t* buffer = channel->buffer; uint32_t bufferLen = channel->bufferLen; union Admin_TxidPrefix prefix = { .values = { .channelNum = admin->messageHeader.channelNum, .serial = channel->serial } }; while (bufferLen > 0) { /* skip newlines and spaces between requests */ while (bufferLen > 0 && ('\r' == *buffer || '\n' == *buffer || ' ' == *buffer)) { buffer++; bufferLen--; } if (0 == bufferLen) { break; } struct Allocator* allocator = admin->allocator->child(admin->allocator); struct Reader* reader = ArrayReader_new(buffer, bufferLen, allocator); Dict message; int res = StandardBencSerializer_get()->parseDictionary(reader, allocator, &message); if (-2 == res) { Log_debug(admin->logger, "Need more data to decode bencoded request on channel [%u].", admin->messageHeader.channelNum); break; // need more data } if (res) { Log_info(admin->logger, "Got unparsable data from admin interface on channel [%u].", admin->messageHeader.channelNum); adminChannelClose(admin, admin->messageHeader.channelNum); return; // buffer is already cleared } uint32_t amount = reader->bytesRead(reader); handleRequestFromChild(admin, &prefix, &message, buffer, amount, allocator); buffer += amount; bufferLen -= amount; allocator->free(allocator); } if (0 != bufferLen && buffer != channel->buffer) { // move data to start of buffer, so we can append new data memmove(channel->buffer, buffer, bufferLen); } channel->bufferLen = bufferLen; }
// only in parent static void inFromChild(evutil_socket_t socket, short eventType, void* vcontext) { struct Admin* admin = (struct Admin*) vcontext; uint8_t buffer[MAX_API_REQUEST_SIZE]; ssize_t amount = read(admin->inFd, buffer, MAX_API_REQUEST_SIZE); if (amount < 1) { if (amount == 0 || errno != EAGAIN) { perror("broken pipe"); event_free(admin->pipeEv); } return; } struct Allocator* tempAllocator = admin->allocator->child(admin->allocator); handleRequestFromChild(admin, buffer, amount, tempAllocator); tempAllocator->free(tempAllocator); }
// only in parent static void inFromChild(evutil_socket_t socket, short eventType, void* vcontext) { struct Admin* admin = (struct Admin*) vcontext; uint8_t buffer[MAX_API_REQUEST_SIZE]; ssize_t amount = read(admin->inFd, buffer, MAX_API_REQUEST_SIZE); if (amount < 1) { if (amount == 0 || errno != EAGAIN) { if (amount < 0) { Log_error1(admin->logger, "Broken pipe to admin process, errno=%d", errno); } else { Log_error(admin->logger, "Connection to admin process closed unexpectedly"); } event_free(admin->pipeEv); } return; } if (!admin->initialized) { if (amount != sizeof(struct sockaddr_storage) + sizeof(int) + 8) { Log_error(admin->logger, "unexpected length"); } else if (memcmp(buffer, "abcd", 4)) { Log_error(admin->logger, "bad magic"); } else if (memcmp(&buffer[sizeof(struct sockaddr_storage) + sizeof(int) + 4], "wxyz", 4)) { Log_error(admin->logger, "bad magic"); } else { Bits_memcpyConst(&admin->addressLength, &buffer[4], sizeof(int)); Bits_memcpyConst(&admin->address, &buffer[4 + sizeof(int)], sizeof(struct sockaddr_storage)); admin->initialized = true; } event_base_loopbreak(admin->eventBase); return; } struct Allocator* tempAllocator = admin->allocator->child(admin->allocator); handleRequestFromChild(admin, buffer, amount, tempAllocator); tempAllocator->free(tempAllocator); }