Browse Source

correct how data from mgmt itf is received

pull/1/head
Heiko Hund 12 years ago
parent
commit
15287dc5ea
  1. 180
      manage.c
  2. 2
      options.h

180
manage.c

@ -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;
pos = memchr(data, (*c->manage.password ? ':' : '\n'), res);
if (!pos)
return; return;
/* There is data available: read it */ data = malloc(c->manage.saved_size + data_size);
res = recv(c->manage.sk, data, pos - data + 1, 0); if (data == NULL)
if (res != pos - data + 1)
return; return;
/* Reply to a management password request */ res = recv(c->manage.sk, data + c->manage.saved_size, data_size, 0);
if (*c->manage.password) if (res != (int) data_size)
{ {
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;
if (rtmsg_handler[log]) c->manage.saved_size = 0;
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 (c->manage.cmd_queue)
offset = 0;
while (offset < data_size)
{ {
/* Response to commands */ char *pos;
mgmt_cmd_t *cmd = c->manage.cmd_queue; char *line = data + offset;
if (strncmp(data, "SUCCESS:", 8) == 0) size_t line_size = data_size - offset;
pos = memchr(line, (*c->manage.password ? ':' : '\n'), line_size);
if (pos == NULL)
{ {
if (cmd->handler) c->manage.saved_data = malloc(data_size);
cmd->handler(c, data + 9); if (c->manage.saved_data)
UnqueueCommand(c); {
c->manage.saved_size = data_size;
memcpy(c->manage.saved_data, line, c->manage.saved_size);
}
break;
} }
else if (strncmp(data, "ERROR:", 6) == 0)
offset += (pos - line) + 1;
/* Reply to a management password request */
if (*c->manage.password)
{ {
if (cmd->handler) ManagementCommand(c, c->manage.password, NULL, regular);
cmd->handler(c, NULL); *c->manage.password = '\0';
UnqueueCommand(c); continue;
} }
else if (strcmp(data, "END") == 0)
/* Handle regular management interface output */
line[pos - line - 1] = '\0';
if (line[0] == '>')
{ {
UnqueueCommand(c); /* 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:", 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 (cmd->handler) else if (c->manage.cmd_queue)
{ {
cmd->handler(c, data); /* 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; 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))

2
options.h

@ -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;

Loading…
Cancel
Save