- return error;
- }
-
- return new_tcp_vconn(name, fd, vconnp);
-}
-
-static void
-tcp_close(struct vconn *vconn)
-{
- struct tcp_vconn *tcp = tcp_vconn_cast(vconn);
- close(tcp->fd);
- free(tcp);
-}
-
-static bool
-tcp_prepoll(struct vconn *vconn, int want, struct pollfd *pfd)
-{
- struct tcp_vconn *tcp = tcp_vconn_cast(vconn);
- pfd->fd = tcp->fd;
- if (want & WANT_RECV) {
- pfd->events |= POLLIN;
- }
- if (want & WANT_SEND || tcp->txbuf) {
- pfd->events |= POLLOUT;
- }
- return false;
-}
-
-static void
-tcp_postpoll(struct vconn *vconn, short int *revents)
-{
- struct tcp_vconn *tcp = tcp_vconn_cast(vconn);
- if (*revents & POLLOUT && tcp->txbuf) {
- ssize_t n = write(tcp->fd, tcp->txbuf->data, tcp->txbuf->size);
- if (n < 0) {
- if (errno != EAGAIN) {
- VLOG_ERR("send: %s", strerror(errno));
- *revents |= POLLERR;
- }
- } else if (n > 0) {
- buffer_pull(tcp->txbuf, n);
- if (tcp->txbuf->size == 0) {
- buffer_delete(tcp->txbuf);
- tcp->txbuf = NULL;
- }
- }
- if (tcp->txbuf) {
- *revents &= ~POLLOUT;
- }
- }
-}
-
-static int
-tcp_recv(struct vconn *vconn, struct buffer **bufferp)
-{
- struct tcp_vconn *tcp = tcp_vconn_cast(vconn);
- struct buffer *rx;
- size_t want_bytes;
- ssize_t retval;
-
- if (tcp->rxbuf == NULL) {
- tcp->rxbuf = buffer_new(1564);
- }
- rx = tcp->rxbuf;
-
-again:
- if (sizeof(struct ofp_header) > rx->size) {
- want_bytes = sizeof(struct ofp_header) - rx->size;
- } else {
- struct ofp_header *oh = rx->data;
- size_t length = ntohs(oh->length);
- if (length < sizeof(struct ofp_header)) {
- VLOG_ERR("received too-short ofp_header (%zu bytes)", length);
- return EPROTO;
- }
- want_bytes = length - rx->size;
- }
- buffer_reserve_tailroom(rx, want_bytes);
-
- retval = read(tcp->fd, buffer_tail(rx), want_bytes);
- if (retval > 0) {
- rx->size += retval;
- if (retval == want_bytes) {
- if (rx->size > sizeof(struct ofp_header)) {
- *bufferp = rx;
- tcp->rxbuf = NULL;
- return 0;
- } else {
- goto again;
- }
- }
- return EAGAIN;
- } else if (retval == 0) {
- return rx->size ? EPROTO : EOF;
- } else {
- return retval ? errno : EAGAIN;
- }
-}
-
-static int
-tcp_send(struct vconn *vconn, struct buffer *buffer)
-{
- struct tcp_vconn *tcp = tcp_vconn_cast(vconn);
- ssize_t retval;
-
- if (tcp->txbuf) {
- return EAGAIN;