int force_read(rdpTls* tls, uint8* data, int bytes) { int total_read; int read; LLOGLN(10, ("force_read:")); total_read = 0; while (total_read < bytes) { LLOGLN(10, ("force_read: reading %d bytes", bytes - total_read)); read = tls_read(tls, data + total_read, bytes - total_read); if (read < 0) { /* disconnect or other error */ return -1; } if (read == 0) { LLOGLN(0, ("force_read: read == 0, sleeping and reading again")); tcp_can_recv(tls->sockfd, 100); continue; } total_read += read; } return total_read; }
/* Process receivable fds, return true if connection should live on */ static int l_rdp_check_fds(rdpInst * inst) { rdpRdp * rdp; RD_BOOL deactivated; int rv; rdp = RDP_FROM_INST(inst); #ifdef _WIN32 WSAResetEvent(rdp->sec->mcs->iso->tcp->wsa_event); #endif rv = 0; if (tcp_can_recv(rdp->sec->mcs->iso->tcp->sock, 0)) { if (!rdp_loop(rdp, &deactivated)) { rv = 1; } } if ((rv != 0) && rdp->redirect) { rdp->redirect = False; if (rdp_reconnect(rdp)) { rv = 0; } } return rv; }
/* Read length bytes from tcp socket to stream and return it. * Appends to stream s if specified, otherwise it uses stream from tcp layer. * Will block until data available. * Returns NULL on error. */ STREAM tcp_recv(rdpTcp * tcp, STREAM s, uint32 length) { int rcvd = 0; uint32 p_offset; uint32 new_length; uint32 end_offset; if (s == NULL) { /* read into "new" stream */ if (length > tcp->in.size) { tcp->in.data = (uint8 *) xrealloc(tcp->in.data, length); tcp->in.size = length; } tcp->in.end = tcp->in.p = tcp->in.data; s = &(tcp->in); } else { /* append to existing stream */ new_length = (s->end - s->data) + length; if (new_length > s->size) { p_offset = s->p - s->data; end_offset = s->end - s->data; s->data = (uint8 *) xrealloc(s->data, new_length); s->size = new_length; s->p = s->data + p_offset; s->end = s->data + end_offset; } } while (length > 0) { #ifndef DISABLE_TLS if (tcp->iso->mcs->sec->tls_connected) { rcvd = tls_read(tcp->iso->mcs->sec->ssl, (char*) s->end, length); if (rcvd < 0) return NULL; } else #endif { if (!ui_select(tcp->iso->mcs->sec->rdp->inst, tcp->sock)) return NULL; /* user quit */ rcvd = recv(tcp->sock, s->end, length, 0); if (rcvd < 0) { if (rcvd == -1 && TCP_BLOCKS) { tcp_can_recv(tcp->sock, 1); rcvd = 0; } else { ui_error(tcp->iso->mcs->sec->rdp->inst, "recv: %s\n", TCP_STRERROR); return NULL; } } else if (rcvd == 0) { ui_error(tcp->iso->mcs->sec->rdp->inst, "Connection closed\n"); return NULL; } } s->end += rcvd; length -= rcvd; } return s; }
STREAM * read_http(rdpTls* tls, int* acontent_length, tbool read_content) { uint8 buf[1024]; tbool done; int bytes; int offset; int processed; int content_length; STREAM* s; char mark[4]; char cc; char* find_text; mark[0] = 0; mark[1] = 0; mark[2] = 0; mark[3] = 0; s = stream_new(64 * 1024); bytes = 0; offset = 0; processed = 0; done = false; while (!done) { if (bytes < 1) { offset = 0; LLOGLN(0, ("read_http: reading 1024")); bytes = tls_read(tls, buf, 1024); if (bytes < 0) { LLOGLN(0, ("read_http: tls_read failed")); stream_free(s); return NULL; } if (bytes == 0) { tcp_can_recv(tls->sockfd, 100); continue; } } cc = buf[offset]; processed++; offset++; bytes--; mark[0] = mark[1]; mark[1] = mark[2]; mark[2] = mark[3]; mark[3] = cc; stream_write_uint8(s, cc); if ((mark[2] == '\n') && (mark[3] == '\n')) { done = true; continue; } if ((mark[0] == '\r') && (mark[1] == '\n') && (mark[2] == '\r') && (mark[3] == '\n')) { done = true; continue; } } LLOGLN(0, ("read_http: bytes %d offset %d", bytes, offset)); tls_return(tls, buf + offset, bytes); find_text = strstr((char*)(s->data), "Content-Length:"); if (find_text == NULL) { LLOGLN(0, ("read_http: can not fine 'Content-Length:' in http")); stream_free(s); return NULL; } offset = 15; while (find_text[offset] == ' ') { offset++; } content_length = atoi(find_text + offset); if (acontent_length != NULL) { *acontent_length = content_length; } if (content_length > 0 && read_content) { while (content_length > 0) { bytes = tls_read(tls, s->p, content_length); if (bytes < 0) { LLOGLN(0, ("read_http: tls_read failed")); stream_free(s); return NULL; } if (bytes == 0) { tcp_can_recv(tls->sockfd, 100); continue; } s->p += bytes; content_length -= bytes; } } return s; }