in src/generic/messages.c [322:435]
int receive_msg(Tcl_Channel f, int *command, int *flags, int *size,
void **data)
{
/* fd_set rfs;
struct timeval timeout; */
int ret, maxsize;
u_long magic;
u_long version;
MsgHeader mh;
/* timeout.tv_usec=0;
timeout.tv_sec=WMSG_TIMEOUT; */
magic = 0;
if (*data == NULL) {
maxsize = 0;
}
else {
maxsize = *size;
}
/* read from socket until timeout or magic header word appears */
while (magic != WMSG_MAGIC) {
ret = Tcl_Read(f, (char *) &magic, sizeof(u_long));
magic = ntohl(magic);
if (ret == -1) {
#ifdef MSGDEBUG
printf("Error reading socket\n");
#endif
return (-1); /* some error */
}
if (ret != sizeof(u_long)) {
#ifdef MSGDEBUG
printf("incomplete read or client disconnected\n");
#endif
errno = EIO;
return (-1); /* incomplete read */
}
}
/* get rest of message header */
ret =
Tcl_Read(f, (char *) &mh.version, sizeof(MsgHeader) - sizeof(u_long));
if (ret == -1) {
#ifdef MSGDEBUG
printf("Error reading socket\n");
#endif
return (-1); /* some error */
}
if (ret != sizeof(MsgHeader) - sizeof(u_long)) {
#ifdef MSGDEBUG
printf("Incomplete header read: %d but expected %d\n", ret,
sizeof(MsgHeader) - sizeof(u_long));
#endif
errno = EIO;
return (-1); /* incomplete read */
}
version = (int) ntohl(mh.version);
if (version > WMSG_VERSION) {
#ifdef MSGDEBUG
printf("Got unknown version %d\n", version);
#endif
#ifdef EPROTONOSUPPORT
errno = EPROTONOSUPPORT;
#else
errno = EIO;
#endif
return (-1); /* unknown version */
}
*command = (int) ntohl(mh.command);
*flags = (*command & 0xffff0000);
*command &= 0xffff;
*size = (int) ntohl(mh.size); /* +1 = zero terminate block */
if (*data == NULL) { /*alloc a buffer */
*data = Tcl_Alloc(*size + 1);
if (*data == NULL) {
errno = ENOMEM;
return (-1); /* no more memory */
}
maxsize = *size + 1;
}
if ((*size + 1) > maxsize) { /* problem: incoming msg larger than buffer */
#ifdef MSGDEBUG
printf("Message larger than receive buffer, reallocating memory\n");
#endif
*data = Tcl_Realloc(*data, *size + 1);
if (*data == NULL) {
errno = ENOMEM;
return (-1); /* no more memory */
}
}
if ((*size) != 0) {
ret = Tcl_Read(f, (char *) *data, (*size));
if (ret == -1) {
#ifdef MSGDEBUG
printf("Error reading data section of message\n");
#endif
return (-1);
}
if (ret != *size) {
#ifdef MSGDEBUG
printf("Incomplete data read: expected %d got %d (%d)\n", *size, ret, Tcl_Eof(f));
#endif
errno = EIO;
return (-1); /* incomplete read */
}
}
/* zero terminate */
((char *) *data)[*size] = '\0';
return (0);
}