/* * Handle management socket events asynchronously */ void OnManagement(SOCKET sk, LPARAM lParam) { int res; char *pos = NULL; char data[MAX_LOG_LENGTH]; connection_t *c = GetConnByManagement(sk); if (c == NULL) return; switch (WSAGETSELECTEVENT(lParam)) { case FD_CONNECT: if (WSAGETSELECTERROR(lParam)) SendMessage(c->hwndStatus, WM_CLOSE, 0, 0); break; case FD_READ: /* Check if there's a complete line to read */ res = recv(c->manage.sk, data, sizeof(data), MSG_PEEK); if (res < 1) return; pos = memchr(data, (*c->manage.password ? ':' : '\n'), res); if (!pos) return; /* There is data available: read it */ res = recv(c->manage.sk, data, pos - data + 1, 0); if (res != pos - data + 1) return; /* Reply to a management password request */ if (*c->manage.password) { ManagementCommand(c, c->manage.password, NULL, regular); *c->manage.password = '******'; return; } /* Handle regular management interface output */ data[pos - data - 1] = '\0'; if (data[0] == '>') { /* Real time notifications */ pos = data + 1; if (strncmp(pos, "LOG:", 4) == 0) { if (rtmsg_handler[log]) rtmsg_handler[log](c, pos + 4); } else if (strncmp(pos, "STATE:", 6) == 0) { if (rtmsg_handler[state]) rtmsg_handler[state](c, pos + 6); } else if (strncmp(pos, "HOLD:", 5) == 0) { if (rtmsg_handler[hold]) rtmsg_handler[hold](c, pos + 5); } else if (strncmp(pos, "PASSWORD:"******"INFO:", 5) == 0) { /* delay until management interface accepts input */ Sleep(100); if (rtmsg_handler[ready]) rtmsg_handler[ready](c, pos + 5); } } else if (c->manage.cmd_queue) { /* Response to commands */ mgmt_cmd_t *cmd = c->manage.cmd_queue; if (strncmp(data, "SUCCESS:", 8) == 0) { if (cmd->handler) cmd->handler(c, data + 9); UnqueueCommand(c); } else if (strncmp(data, "ERROR:", 6) == 0) { if (cmd->handler) cmd->handler(c, NULL); UnqueueCommand(c); } else if (strcmp(data, "END") == 0) { UnqueueCommand(c); } else if (cmd->handler) { cmd->handler(c, data); } } break; case FD_WRITE: SendCommand(c); break; case FD_CLOSE: closesocket(c->manage.sk); c->manage.sk = INVALID_SOCKET; while (UnqueueCommand(c)) ; WSACleanup(); if (rtmsg_handler[stop]) rtmsg_handler[stop](c, ""); break; } }
/* * Handle management socket events asynchronously */ void OnManagement(SOCKET sk, LPARAM lParam) { int res; char *data; ULONG data_size, offset; connection_t *c = GetConnByManagement(sk); if (c == NULL) return; switch (WSAGETSELECTEVENT(lParam)) { case FD_CONNECT: if (WSAGETSELECTERROR(lParam)) { if (time(NULL) < c->manage.timeout) connect(c->manage.sk, (SOCKADDR *)&c->manage.skaddr, sizeof(c->manage.skaddr)); else { /* Connection to MI timed out. */ c->state = timedout; rtmsg_handler[stop](c, ""); } } break; case FD_READ: if (ioctlsocket(c->manage.sk, FIONREAD, &data_size) != 0 || data_size == 0) return; data = malloc(c->manage.saved_size + data_size); if (data == NULL) return; res = recv(c->manage.sk, data + c->manage.saved_size, data_size, 0); if (res != (int) data_size) { free(data); return; } /* Copy previously saved management data */ if (c->manage.saved_size) { memcpy(data, c->manage.saved_data, c->manage.saved_size); data_size += c->manage.saved_size; free(c->manage.saved_data); c->manage.saved_data = NULL; c->manage.saved_size = 0; } offset = 0; while (offset < data_size) { char *pos; char *line = data + offset; size_t line_size = data_size - offset; pos = memchr(line, (*c->manage.password ? ':' : '\n'), line_size); if (pos == NULL) { c->manage.saved_data = malloc(line_size); if (c->manage.saved_data) { c->manage.saved_size = line_size; memcpy(c->manage.saved_data, line, c->manage.saved_size); } break; } offset += (pos - line) + 1; /* Reply to a management password request */ if (*c->manage.password) { ManagementCommand(c, c->manage.password, NULL, regular); *c->manage.password = '******'; continue; } /* Handle regular management interface output */ line[pos - line - 1] = '\0'; if (line[0] == '>') { /* Real time notifications */ pos = line + 1; if (strncmp(pos, "LOG:", 4) == 0) { if (rtmsg_handler[log]) rtmsg_handler[log](c, pos + 4); } else if (strncmp(pos, "STATE:", 6) == 0) { if (rtmsg_handler[state]) rtmsg_handler[state](c, pos + 6); } else if (strncmp(pos, "HOLD:", 5) == 0) { if (rtmsg_handler[hold]) rtmsg_handler[hold](c, pos + 5); } else if (strncmp(pos, "PASSWORD:"******"PROXY:", 6) == 0) { if (rtmsg_handler[proxy]) rtmsg_handler[proxy](c, pos + 6); } else if (strncmp(pos, "INFO:", 5) == 0) { /* delay until management interface accepts input */ Sleep(100); if (rtmsg_handler[ready]) rtmsg_handler[ready](c, pos + 5); } } else if (c->manage.cmd_queue) { /* Response to commands */ mgmt_cmd_t *cmd = c->manage.cmd_queue; if (strncmp(line, "SUCCESS:", 8) == 0) { if (cmd->handler) cmd->handler(c, line + 9); UnqueueCommand(c); } else if (strncmp(line, "ERROR:", 6) == 0) { if (cmd->handler) cmd->handler(c, NULL); UnqueueCommand(c); } else if (strcmp(line, "END") == 0) { UnqueueCommand(c); } else if (cmd->handler) { cmd->handler(c, line); } } } free(data); break; case FD_WRITE: SendCommand(c); break; case FD_CLOSE: if (c->manage.saved_size) { free(c->manage.saved_data); c->manage.saved_data = NULL; c->manage.saved_size = 0; } closesocket(c->manage.sk); c->manage.sk = INVALID_SOCKET; while (UnqueueCommand(c)) ; WSACleanup(); if (rtmsg_handler[stop]) rtmsg_handler[stop](c, ""); break; } }