2 * Copyright (c) 1998 Adrian Sun (asun@zoology.washington.edu)
3 * All rights reserved. See COPYRIGHT.
5 * this file provides the following functions:
6 * dsi_stream_write: just write a bunch of bytes.
7 * dsi_stream_read: just read a bunch of bytes.
8 * dsi_stream_send: send a DSI header + data.
9 * dsi_stream_receive: read a DSI header + data.
14 #endif /* HAVE_CONFIG_H */
25 #include <sys/types.h>
26 #include <sys/socket.h>
29 #include <atalk/logger.h>
30 #include <atalk/dsi.h>
31 #include <netatalk/endian.h>
32 #include <atalk/util.h>
34 #define min(a,b) ((a) < (b) ? (a) : (b))
37 #define MSG_MORE 0x8000
41 #define MSG_DONTWAIT 0x40
44 /* ----------------------
45 afpd is sleeping too much while trying to send something.
46 May be there's no reader or the reader is also sleeping in write,
47 look if there's some data for us to read, hopefully it will wake up
48 the reader so we can write again.
50 static int dsi_peek(DSI *dsi)
52 fd_set readfds, writefds;
57 LOG(log_debug, logtype_dsi, "dsi_peek");
61 FD_SET( dsi->socket, &readfds);
62 FD_SET( dsi->socket, &writefds);
63 maxfd = dsi->socket +1;
66 FD_SET( dsi->socket, &readfds);
67 FD_SET( dsi->socket, &writefds);
69 /* No timeout: if there's nothing to read nor nothing to write,
70 * we've got nothing to do at all */
71 if ((ret = select( maxfd, &readfds, &writefds, NULL, NULL)) <= 0) {
72 if (ret == -1 && errno == EINTR)
73 /* we might have been interrupted by out timer, so restart select */
76 LOG(log_error, logtype_dsi, "dsi_peek: unexpected select return: %d %s",
77 ret, ret < 0 ? strerror(errno) : "");
81 /* Check if there's sth to read, hopefully reading that will unblock the client */
82 if (FD_ISSET(dsi->socket, &readfds)) {
83 len = dsi->end - dsi->eof;
86 /* ouch, our buffer is full ! fall back to blocking IO
87 * could block and disconnect but it's better than a cpu hog */
88 LOG(log_warning, logtype_dsi, "dsi_peek: read buffer is full");
92 if ((len = read(dsi->socket, dsi->eof, len)) <= 0) {
94 LOG(log_error, logtype_dsi, "dsi_peek: EOF");
97 LOG(log_error, logtype_dsi, "dsi_peek: read: %s", strerror(errno));
102 LOG(log_debug, logtype_dsi, "dsi_peek: read %d bytes", len);
107 if (FD_ISSET(dsi->socket, &writefds)) {
108 /* we can write again */
109 LOG(log_debug, logtype_dsi, "dsi_peek: can write again");
117 /* ------------------------------
118 * write raw data. return actual bytes read. checks against EINTR
119 * aren't necessary if all of the signals have SA_RESTART
121 ssize_t dsi_stream_write(DSI *dsi, void *data, const size_t length, int mode)
125 unsigned int flags = 0;
130 LOG(log_maxdebug, logtype_dsi, "dsi_stream_write: sending %u bytes", length);
132 while (written < length) {
133 len = send(dsi->socket, (u_int8_t *) data + written, length - written, flags);
142 if (errno == EAGAIN || errno == EWOULDBLOCK) {
143 if (mode == DSI_NOWAIT && written == 0) {
144 /* DSI_NOWAIT is used by attention give up in this case. */
149 /* Try to read sth. in order to break up possible deadlock */
150 if (dsi_peek(dsi) != 0) {
154 /* Now try writing again */
158 LOG(log_error, logtype_dsi, "dsi_stream_write: %s", strerror(errno));
163 dsi->write_count += written;
171 /* ---------------------------------
174 ssize_t dsi_stream_read_file(DSI *dsi, int fromfd, off_t offset, const size_t length)
179 LOG(log_maxdebug, logtype_dsi, "dsi_stream_read_file: sending %u bytes", length);
184 while (written < length) {
185 len = sys_sendfile(dsi->socket, fromfd, &offset, length - written);
190 if (errno == EINVAL || errno == ENOSYS)
193 if (errno == EAGAIN || errno == EWOULDBLOCK) {
195 /* can't go back to blocking mode, exit, the next read
196 will return with an error and afpd will die.
202 LOG(log_error, logtype_dsi, "dsi_stream_read_file: %s", strerror(errno));
206 /* afpd is going to exit */
208 return -1; /* I think we're at EOF here... */
214 dsi->write_count += written;
221 * Return all bytes up to count from dsi->buffer if there are any buffered there
223 static size_t from_buf(DSI *dsi, u_int8_t *buf, size_t count)
227 LOG(log_maxdebug, logtype_dsi, "from_buf: %u bytes", count);
230 nbe = dsi->eof - dsi->start;
233 nbe = min((size_t)nbe, count);
234 memcpy(buf, dsi->start, nbe);
237 if (dsi->eof == dsi->start)
238 dsi->start = dsi->eof = dsi->buffer;
246 * Get bytes from buffer dsi->buffer or read from socket
248 * 1. Check if there are bytes in the the dsi->buffer buffer.
249 * 2. Return bytes from (1) if yes.
250 * Note: this may return fewer bytes then requested in count !!
251 * 3. If the buffer was empty, read from the socket.
253 static ssize_t buf_read(DSI *dsi, u_int8_t *buf, size_t count)
257 LOG(log_maxdebug, logtype_dsi, "buf_read: %u bytes", count);
262 nbe = from_buf(dsi, buf, count); /* 1. */
266 return readt(dsi->socket, buf, count, 0, 1); /* 3. */
270 * Essentially a loop around buf_read() to ensure "length" bytes are read
271 * from dsi->buffer and/or the socket.
273 size_t dsi_stream_read(DSI *dsi, void *data, const size_t length)
278 LOG(log_maxdebug, logtype_dsi, "dsi_stream_read: %u bytes", length);
281 while (stored < length) {
282 len = buf_read(dsi, (u_int8_t *) data + stored, length - stored);
283 if (len == -1 && (errno == EINTR || errno == EAGAIN)) {
284 LOG(log_debug, logtype_dsi, "dsi_stream_read: select read loop");
286 } else if (len > 0) {
288 } else { /* eof or error */
289 /* don't log EOF error if it's just after connect (OSX 10.3 probe) */
290 if (len || stored || dsi->read_count) {
291 if (! (dsi->flags & DSI_DISCONNECTED))
292 LOG(log_error, logtype_dsi, "dsi_stream_read: len:%d, %s",
293 dsi->socket, len, (len < 0) ? strerror(errno) : "unexpected EOF");
299 dsi->read_count += stored;
304 * Get "length" bytes from buffer and/or socket. In order to avoid frequent small reads
305 * this tries to read larger chunks (65536 bytes) into a buffer.
307 static size_t dsi_buffered_stream_read(DSI *dsi, u_int8_t *data, const size_t length)
312 LOG(log_maxdebug, logtype_dsi, "dsi_buffered_stream_read: %u bytes", length);
314 len = from_buf(dsi, data, length); /* read from buffer dsi->buffer */
315 dsi->read_count += len;
316 if (len == length) { /* got enough bytes from there ? */
317 return len; /* yes */
320 /* fill the buffer with 65536 bytes or until buffer is full */
321 buflen = min(65536, dsi->end - dsi->eof);
324 ret = read(dsi->socket, dsi->eof, buflen);
329 /* now get the remaining data */
330 len += dsi_stream_read(dsi, data + len, length - len);
334 /* ---------------------------------------
336 static void block_sig(DSI *dsi)
341 /* ---------------------------------------
343 static void unblock_sig(DSI *dsi)
348 /* ---------------------------------------
349 * write data. 0 on failure. this assumes that dsi_len will never
350 * cause an overflow in the data buffer.
352 int dsi_stream_send(DSI *dsi, void *buf, size_t length)
354 char block[DSI_BLOCKSIZ];
359 LOG(log_maxdebug, logtype_dsi, "dsi_stream_send: %u bytes",
360 length ? length : sizeof(block));
362 block[0] = dsi->header.dsi_flags;
363 block[1] = dsi->header.dsi_command;
364 memcpy(block + 2, &dsi->header.dsi_requestID,
365 sizeof(dsi->header.dsi_requestID));
366 memcpy(block + 4, &dsi->header.dsi_code, sizeof(dsi->header.dsi_code));
367 memcpy(block + 8, &dsi->header.dsi_len, sizeof(dsi->header.dsi_len));
368 memcpy(block + 12, &dsi->header.dsi_reserved,
369 sizeof(dsi->header.dsi_reserved));
371 if (!length) { /* just write the header */
372 length = (dsi_stream_write(dsi, block, sizeof(block), 0) == sizeof(block));
373 return length; /* really 0 on failure, 1 on success */
378 iov[0].iov_base = block;
379 iov[0].iov_len = sizeof(block);
380 iov[1].iov_base = buf;
381 iov[1].iov_len = length;
383 towrite = sizeof(block) + length;
384 dsi->write_count += towrite;
385 while (towrite > 0) {
386 if (((len = writev(dsi->socket, iov, 2)) == -1 && errno == EINTR) ||
390 if ((size_t)len == towrite) /* wrote everything out */
392 else if (len < 0) { /* error */
393 if (errno == EAGAIN || errno == EWOULDBLOCK) {
394 if (!dsi_peek(dsi)) {
398 LOG(log_error, logtype_dsi, "dsi_stream_send: %s", strerror(errno));
404 if (towrite > length) { /* skip part of header */
405 iov[0].iov_base = (char *) iov[0].iov_base + len;
406 iov[0].iov_len -= len;
407 } else { /* skip to data */
408 if (iov[0].iov_len) {
409 len -= iov[0].iov_len;
412 iov[1].iov_base = (char *) iov[1].iov_base + len;
413 iov[1].iov_len -= len;
422 /* ---------------------------------------
423 * read data. function on success. 0 on failure. data length gets
424 * stored in length variable. this should really use size_t's, but
425 * that would require changes elsewhere. */
426 int dsi_stream_receive(DSI *dsi, void *buf, const size_t ilength,
429 char block[DSI_BLOCKSIZ];
431 LOG(log_maxdebug, logtype_dsi, "dsi_stream_receive: %u bytes", ilength);
433 /* read in the header */
434 if (dsi_buffered_stream_read(dsi, (u_int8_t *)block, sizeof(block)) != sizeof(block))
437 dsi->header.dsi_flags = block[0];
438 dsi->header.dsi_command = block[1];
439 /* FIXME, not the right place,
440 but we get a server disconnect without reason in the log
443 LOG(log_error, logtype_dsi, "dsi_stream_receive: invalid packet, fatal");
447 memcpy(&dsi->header.dsi_requestID, block + 2,
448 sizeof(dsi->header.dsi_requestID));
449 memcpy(&dsi->header.dsi_code, block + 4, sizeof(dsi->header.dsi_code));
450 memcpy(&dsi->header.dsi_len, block + 8, sizeof(dsi->header.dsi_len));
451 memcpy(&dsi->header.dsi_reserved, block + 12,
452 sizeof(dsi->header.dsi_reserved));
453 dsi->clientID = ntohs(dsi->header.dsi_requestID);
455 /* make sure we don't over-write our buffers. */
456 *rlength = min(ntohl(dsi->header.dsi_len), ilength);
457 if (dsi_stream_read(dsi, buf, *rlength) != *rlength)