X-Git-Url: http://git.joshuawise.com/netwatch.git/blobdiff_plain/8ceb05150562e3b953f4846d0b82ca2026cf4560..2c9b12c13a216fbaca15d3c0d4bf0b994950117f:/net/rfb.c?ds=sidebyside diff --git a/net/rfb.c b/net/rfb.c index eac1bdd..1f620f0 100644 --- a/net/rfb.c +++ b/net/rfb.c @@ -164,12 +164,11 @@ static void send_fsm(struct tcp_pcb *pcb, struct rfb_state *state) { break; } - /* potential FALL THROUGH */ - + /* FALL THROUGH to SST_NEEDS_UPDATE*/ case SST_NEEDS_UPDATE: outputf("RFB send: sending header"); /* Send a header */ - state->frame_bytes = fb->curmode.xres * fb->curmode.yres * 3; /* XXX */ + state->frame_bytes = fb->curmode.xres * fb->curmode.yres * fb->curmode.bytestride; hdr.msgtype = 0; hdr.nrects = htons(1); hdr.xpos = htons(0); @@ -177,46 +176,51 @@ static void send_fsm(struct tcp_pcb *pcb, struct rfb_state *state) { hdr.width = htons(fb->curmode.xres); hdr.height = htons(fb->curmode.yres); hdr.enctype = htonl(0); - tcp_write(pcb, &hdr, sizeof(hdr), 0); - tcp_output(pcb); + tcp_write(pcb, &hdr, sizeof(hdr), TCP_WRITE_FLAG_COPY); state->update_pos = 0; state->send_state = SST_SENDING; - /* FALL THROUGH */ - + /* FALL THROUGH to SST_SENDING*/ case SST_SENDING: - left = state->frame_bytes - state->update_pos; + while (1) { + left = state->frame_bytes - state->update_pos; - if (left > tcp_sndbuf(pcb)) { - sndlength = tcp_sndbuf(pcb); - } else { - sndlength = left; - } + if (left == 0) { + state->send_state = SST_IDLE; + break; + } + + if (left > 8192) /* Sounds good enough to me. */ + left = 8192; - do { - err = tcp_write(pcb, fb->fbaddr + state->update_pos, sndlength, 0); - if (err == ERR_MEM) { - outputf("RFB: ERR_MEM sending %d", sndlength); - sndlength /= 2; + sndlength = left; + do { + err = tcp_write(pcb, fb->fbaddr + state->update_pos, sndlength, TCP_WRITE_FLAG_COPY /* The card can't DMA from there. */); + if (err == ERR_MEM) /* Back down until lwip says we've got space. */ + sndlength /= 2; + } while (err == ERR_MEM && sndlength > 1); + + if (err != ERR_OK) { + if (err != ERR_MEM) + outputf("RFB: send error %d", err); + + /* We'll just give up for now and come back when we have space later. */ + break; } - } while (err == ERR_MEM && sndlength > 1); - if (err == ERR_OK) { - outputf("RFB: sent %d", sndlength); state->update_pos += sndlength; - } else { - outputf("RFB: send error %d", err); - } - - tcp_output(pcb); - if (state->update_pos == state->frame_bytes) { - state->send_state = SST_IDLE; + if (tcp_sndbuf(pcb) == 0) { + break; + } } break; } + + if (tcp_output(pcb) != ERR_OK) + outputf("RFB: tcp_output bailed in send_fsm?"); } static err_t rfb_sent(void *arg, struct tcp_pcb *pcb, uint16_t len) { @@ -296,7 +300,7 @@ static enum fsm_result recv_fsm(struct tcp_pcb *pcb, struct rfb_state *state) { state->state = ST_MAIN; outputf("RFB: Sending server info", state->version); - tcp_write(pcb, &server_info, sizeof(server_info), 0); + tcp_write(pcb, &server_info, sizeof(server_info), TCP_WRITE_FLAG_COPY); tcp_output(pcb); return OK; @@ -334,7 +338,6 @@ static enum fsm_result recv_fsm(struct tcp_pcb *pcb, struct rfb_state *state) { for (i = 0; i < ntohs(req->num); i++) { outputf("RFB: Encoding: %d", ntohl(req->encodings[i])); /* XXX ... */ - } state->readpos += pktsize; @@ -441,7 +444,7 @@ static err_t rfb_recv(void *arg, struct tcp_pcb *pcb, case OK: outputf("RFB FSM: ok"); - /* Might as well send now... */ + /* Kick off a send. */ if (state->send_state == SST_IDLE && state->update_requested) { send_fsm(pcb, state);