transport.c (2351B)
1 /* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> 2 * See LICENSE file for license details. 3 */ 4 #include <errno.h> 5 #include <fcntl.h> 6 #include <stdio.h> 7 #include <stdlib.h> 8 #include <string.h> 9 #include <sys/stat.h> 10 #include <sys/socket.h> 11 #include <sys/un.h> 12 #include <unistd.h> 13 #include "ixp_local.h" 14 15 static int 16 mread(int fd, IxpMsg *msg, uint count) { 17 int r, n; 18 19 n = msg->end - msg->pos; 20 if(n <= 0) { 21 werrstr("buffer full"); 22 return -1; 23 } 24 if(n > count) 25 n = count; 26 27 r = thread->read(fd, msg->pos, n); 28 if(r > 0) 29 msg->pos += r; 30 return r; 31 } 32 33 static int 34 readn(int fd, IxpMsg *msg, uint count) { 35 uint num; 36 int r; 37 38 num = count; 39 while(num > 0) { 40 r = mread(fd, msg, num); 41 if(r == -1 && errno == EINTR) 42 continue; 43 if(r == 0) { 44 werrstr("broken pipe: %s", ixp_errbuf()); 45 return count - num; 46 } 47 num -= r; 48 } 49 return count - num; 50 } 51 52 /** 53 * Function: ixp_sendmsg 54 * Function: ixp_recvmsg 55 * 56 * These functions read and write messages to and from the given 57 * file descriptors. 58 * 59 * ixp_sendmsg writes the data at P<msg>->pos upto P<msg>->end. 60 * If the call returns non-zero, all data is assured to have 61 * been written. 62 * 63 * ixp_recvmsg first reads a 32 bit, little-endian length from 64 * P<fd> and then reads a message of that length (including the 65 * 4 byte size specifier) into the buffer at P<msg>->data, so 66 * long as the size is less than P<msg>->size. 67 * 68 * Returns: 69 * These functions return the number of bytes read or 70 * written, or 0 on error. Errors are stored in 71 * F<ixp_errbuf>. 72 */ 73 uint 74 ixp_sendmsg(int fd, IxpMsg *msg) { 75 int r; 76 77 msg->pos = msg->data; 78 while(msg->pos < msg->end) { 79 r = thread->write(fd, msg->pos, msg->end - msg->pos); 80 if(r < 1) { 81 if(errno == EINTR) 82 continue; 83 werrstr("broken pipe: %s", ixp_errbuf()); 84 return 0; 85 } 86 msg->pos += r; 87 } 88 return msg->pos - msg->data; 89 } 90 91 uint 92 ixp_recvmsg(int fd, IxpMsg *msg) { 93 enum { SSize = 4 }; 94 uint32_t msize, size; 95 96 msg->mode = MsgUnpack; 97 msg->pos = msg->data; 98 msg->end = msg->data + msg->size; 99 if(readn(fd, msg, SSize) != SSize) 100 return 0; 101 102 msg->pos = msg->data; 103 ixp_pu32(msg, &msize); 104 105 size = msize - SSize; 106 if(size >= msg->end - msg->pos) { 107 werrstr("message too large"); 108 return 0; 109 } 110 if(readn(fd, msg, size) != size) { 111 werrstr("message incomplete"); 112 return 0; 113 } 114 115 msg->end = msg->pos; 116 return msize; 117 } 118