1 #include <stdio.h> 2 3 #include "api_exch.h" 4 5 static char ibuffer[40], *ibuf_next, *ibuf_last; 6 #define IBUFADDED(i) ibuf_last += (i) 7 #define IBUFAVAILABLE() (ibuf_last -ibuf_next) 8 #define IBUFFER() ibuffer 9 #define IBUFGETCHAR() (*ibuf_next++) 10 #define IBUFGETSHORT() ((*ibuf_next++<<8)|(*ibuf_next++&0xff)) 11 #define IBUFRESET() (ibuf_next = ibuf_last = ibuffer) 12 13 char obuffer[40], *obuf_next; 14 #define OBUFADDBYTES(w,l) { memcpy(obuf_next, w, l); obuf_next += l; } 15 #define OBUFADDCHAR(c) (*obuf_next++ = c) 16 #define OBUFADDSHORT(s) {*obuf_next++ = (s)>>8; *obuf_next++ = s; } 17 #define OBUFAVAILABLE() (obuf_next - obuffer) 18 #define OBUFFER() obuffer 19 #define OBUFRESET() obuf_next = obuffer 20 #define OBUFROOM() (obuffer+sizeof obuffer-obuf_next) 21 22 23 static int 24 outflush() 25 { 26 int length = OBUFAVAILABLE(); 27 28 if (length != 0) { 29 if (write(sock, OBUFFER(), length) != length) { 30 perror("writing to API client"); 31 return -1; 32 } 33 OBUFRESET(); 34 } 35 return 0; /* All OK */ 36 } 37 38 39 static int 40 infill(count) 41 int count; 42 { 43 int i; 44 45 if (OBUFAVAILABLE()) { 46 if (outflush() == -1) { 47 return -1; 48 } 49 } 50 if (ibuf_next == ibuf_last) { 51 IBUFRESET(); 52 } 53 while (count) { 54 if ((i = read(sock, IBUFFER(), count)) < 0) { 55 perror("reading from API client"); 56 return -1; 57 } 58 count -= i; 59 IBUFADDED(i); 60 } 61 return 0; 62 } 63 64 static int 65 api_exch_incommand(command) 66 int command; 67 { 68 int i; 69 70 if (IBUFAVAILABLE() < 1) { 71 if (infill(1) == -1) { 72 return -1; 73 } 74 } 75 i = IBUFGETCHAR(); 76 if (i != command) { 77 fprintf(stderr, "Expected API command 0x%x, got API command 0x%x.\n", 78 command, i); 79 return -1; 80 } 81 return 0; 82 } 83 84 85 static int 86 api_exch_outcommand(command) 87 int command; 88 { 89 if (OBUFROOM() < 1) { 90 if (outflush() == -1) { 91 return -1; 92 } 93 } 94 OBUFADDCHAR(command); 95 return 0; 96 } 97 98 99 static int 100 api_exch_outtype(type, length, location) 101 int 102 type, 103 length; 104 char 105 *location; 106 { 107 int netleng = htons(length); 108 109 if (OBUFROOM() < 3) { 110 if (outflush() == -1) { 111 return -1; 112 } 113 } 114 OBUFADDCHAR(type); 115 OBUFADDSHORT(netleng); 116 if (OBUFROOM() > length) { 117 OBUFADDBYTES(location, length); 118 } else { 119 if (outflush() == -1) { 120 return -1; 121 } 122 if (write(sock, location, length) != length) { 123 perror("writing to API client"); 124 return -1; 125 } 126 } 127 } 128 129 130 static int 131 api_exch_intype(type, length, location) 132 int 133 type, 134 length; 135 char 136 *location; 137 { 138 int i, netleng = htons(length); 139 140 if (IBUFAVAILABLE() < 3) { 141 if (infill(3) == -1) { 142 return -1; 143 } 144 } 145 if ((i = IBUFGETCHAR()) != type) { 146 fprintf(stderr, "Expected type 0x%x, got type 0x%x.\n", type, i); 147 return -1; 148 } 149 if ((i = IBUFGETSHORT()) != netleng) { 150 fprintf(stderr, "Type 0x%x - expected length %d, received length %d.\n", 151 type, length, ntohs(i)); 152 return -1; 153 } 154 while (length) { 155 if ((i = read(sock, location, length)) < 0) { 156 perror("reading from API client"); 157 return -1; 158 } 159 length -= i; 160 location += i; 161 } 162 return 0; 163 } 164