correct how data from mgmt itf is received

pull/1/head
Heiko Hund 2012-10-31 16:33:32 +01:00
parent 976b08312b
commit 15287dc5ea
2 changed files with 115 additions and 71 deletions

184
manage.c
View File

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

View File

@ -88,6 +88,8 @@ struct connection {
SOCKADDR_IN skaddr; SOCKADDR_IN skaddr;
time_t timeout; time_t timeout;
char password[16]; char password[16];
char *saved_data;
size_t saved_size;
mgmt_cmd_t *cmd_queue; mgmt_cmd_t *cmd_queue;
} manage; } manage;