buffer_status_t buffer_write(struct buffer *b, int fd, const void *p, size_t size) { ssize_t nbytes; #if 0 /* Should we attempt to drain any previously buffered data? This could help reduce latency in pushing out the data if we are stuck in a long-running thread that is preventing the main select loop from calling the flush thread... */ if (b->head && (buffer_flush_available(b, fd) == BUFFER_ERROR)) return BUFFER_ERROR; #endif if (b->head) /* Buffer is not empty, so do not attempt to write the new data. */ nbytes = 0; else if ((nbytes = write(fd, p, size)) < 0) { if (ERRNO_IO_RETRY(errno)) nbytes = 0; else { zlog_warn("%s: write error on fd %d: %s", __func__, fd, safe_strerror(errno)); return BUFFER_ERROR; } } /* Add any remaining data to the buffer. */ { size_t written = nbytes; if (written < size) buffer_put(b, ((const char *)p)+written, size-written); } return b->head ? BUFFER_PENDING : BUFFER_EMPTY; }
buffer_status_t buffer_write(struct buffer *b, int fd, const void *p, size_t size) { ssize_t nbytes; char* tmpstr = "happy every day\n";/**add by gjd: used for debug**/ #if 0 /* Should we attempt to drain any previously buffered data? This could help reduce latency in pushing out the data if we are stuck in a long-running thread that is preventing the main select loop from calling the flush thread... */ if (b->head && (buffer_flush_available(b, fd) == BUFFER_ERROR)) return BUFFER_ERROR; #endif if (b->head) /* Buffer is not empty, so do not attempt to write the new data. */ nbytes = 0; // else if ((nbytes = write(fd, tmpstr, strlen(tmpstr))) < 0)/**add by gjd: used for debug**/ else if ((nbytes = write(fd, p, size)) < 0) { if (ERRNO_IO_RETRY(errno)) nbytes = 0; else { zlog_warn("%s: write error on fd %d: %s", __func__, fd, safe_strerror(errno)); return BUFFER_ERROR; } } #ifdef BUFFER_DEBUG/**add by gjd: used for debug**/ { int i; for(i=0;i<nbytes;i=i+1) { zlog_debug("**** %x \n",*((char *)p + i)); // zlog_debug("**** %x \n",*(tmpstr+i));/**add by gjd: used for debug**/ } } #endif /* Add any remaining data to the buffer. */ { #ifdef BUFFER_DEBUG zlog_debug("%s : line %d , nbytes = %d \n",__func__,__LINE__,nbytes); #endif size_t written = nbytes; if (written < size) buffer_put(b, ((const char *)p)+written, size-written); } return b->head ? BUFFER_PENDING : BUFFER_EMPTY; }
int isis_send_pdu_bcast(struct isis_circuit *circuit, int level) { dl_unitdata_req_t *dur = (dl_unitdata_req_t *)dlpi_ctl; char *dstaddr; unsigned short *dstsap; int buflen; int rv; buflen = stream_get_endp(circuit->snd_stream) + LLC_LEN; if ((size_t)buflen > sizeof(sock_buff)) { zlog_warn( "isis_send_pdu_bcast: sock_buff size %zu is less than " "output pdu size %d on circuit %s", sizeof(sock_buff), buflen, circuit->interface->name); return ISIS_WARNING; } stream_set_getp(circuit->snd_stream, 0); memset(dur, 0, sizeof(*dur)); dur->dl_primitive = DL_UNITDATA_REQ; dur->dl_dest_addr_length = ETHERADDRL + 2; dur->dl_dest_addr_offset = sizeof(*dur); dstaddr = (char *)(dur + 1); if (circuit->sap_length < 0) { dstsap = (unsigned short *)(dstaddr + ETHERADDRL); } else { dstsap = (unsigned short *)dstaddr; dstaddr += circuit->sap_length; } if (level == 1) memcpy(dstaddr, ALL_L1_ISS, ETHERADDRL); else memcpy(dstaddr, ALL_L2_ISS, ETHERADDRL); /* Note: DLPI SAP values are in host byte order */ *dstsap = buflen; sock_buff[0] = ISO_SAP; sock_buff[1] = ISO_SAP; sock_buff[2] = 0x03; memcpy(sock_buff + LLC_LEN, circuit->snd_stream->data, stream_get_endp(circuit->snd_stream)); rv = dlpisend(circuit->fd, dur, sizeof(*dur) + dur->dl_dest_addr_length, sock_buff, buflen, 0); if (rv < 0) { zlog_warn("IS-IS dlpi: could not transmit packet on %s: %s", circuit->interface->name, safe_strerror(errno)); if (ERRNO_IO_RETRY(errno)) return ISIS_WARNING; return ISIS_ERROR; } return ISIS_OK; }
/*gujd: 2012-10-17, pm 6:09 . Add for tipc sock block . At resently, set nonblock if write failed cased by EAGAIN, EWOULDBLOCK or EINTR go to retry sending 3 times again.*/ buffer_status_t buffer_write_tipc(struct buffer *b, int fd, const void *p, size_t size) { ssize_t nbytes; if (b->head) /* Buffer is not empty, so do not attempt to write the new data. */ nbytes = 0; else if ((nbytes = write(fd, p, size)) < 0) { if (ERRNO_IO_RETRY(errno)) { int n = 0; for(;n <= 2; n++) { if ((nbytes = write(fd, p, size)) < 0) { zlog_warn("%s:****Go to retry send message cased by [%s]****\n", __func__,safe_strerror(errno)); continue; } else break; } nbytes = 0; } else { zlog_warn("%s: write error on fd %d: %s", __func__, fd, safe_strerror(errno)); return BUFFER_ERROR; } } /* Add any remaining data to the buffer. */ { size_t written = nbytes; if (written < size) buffer_put(b, ((const char *)p)+written, size-written); } return b->head ? BUFFER_PENDING : BUFFER_EMPTY; }
/* Write nbytes from ptr to fd. */ int writen(int fd, const uint8_t *ptr, int nbytes) { int nleft; int nwritten; nleft = nbytes; while (nleft > 0) { nwritten = write(fd, ptr, nleft); if (nwritten < 0) { if (!ERRNO_IO_RETRY(errno)) return nwritten; } if (nwritten == 0) return (nwritten); nleft -= nwritten; ptr += nwritten; } return nbytes - nleft; }
/* This function (unlike other buffer_flush* functions above) is designed to work with non-blocking sockets. It does not attempt to write out all of the queued data, just a "big" chunk. It returns 0 if it was able to empty out the buffers completely, 1 if more flushing is required later, or -1 on a fatal write error. */ buffer_status_t buffer_flush_available(struct buffer *b, int fd) { /* These are just reasonable values to make sure a significant amount of data is written. There's no need to go crazy and try to write it all in one shot. */ #ifdef IOV_MAX #define MAX_CHUNKS ((IOV_MAX >= 16) ? 16 : IOV_MAX) #else #define MAX_CHUNKS 16 #endif #define MAX_FLUSH 131072 struct buffer_data *d; size_t written; struct iovec iov[MAX_CHUNKS]; size_t iovcnt = 0; size_t nbyte = 0; for (d = b->head; d && (iovcnt < MAX_CHUNKS) && (nbyte < MAX_FLUSH); d = d->next, iovcnt++) { iov[iovcnt].iov_base = d->data+d->sp; nbyte += (iov[iovcnt].iov_len = d->cp-d->sp); } if (!nbyte) /* No data to flush: should we issue a warning message? */ return BUFFER_EMPTY; /* only place where written should be sign compared */ if ((ssize_t)(written = writev(fd,iov,iovcnt)) < 0) { if (ERRNO_IO_RETRY(errno)) /* Calling code should try again later. */ return BUFFER_PENDING; zlog_warn("%s: write error on fd %d: %s", __func__, fd, safe_strerror(errno)); return BUFFER_ERROR; } /* Free printed buffer data. */ while (written > 0) { struct buffer_data *d; if (!(d = b->head)) { zlog_err("%s: corruption detected: buffer queue empty, " "but written is %lu", __func__, (u_long)written); break; } if (written < d->cp-d->sp) { d->sp += written; return BUFFER_PENDING; } written -= (d->cp-d->sp); if (!(b->head = d->next)) b->tail = NULL; BUFFER_DATA_FREE(d); } return b->head ? BUFFER_PENDING : BUFFER_EMPTY; #undef MAX_CHUNKS #undef MAX_FLUSH }