message.c (5917B)
1 /* Copyright ©2007-2010 Kris Maglione <maglione.k at Gmail> 2 * See LICENSE file for license details. 3 */ 4 #include <stdlib.h> 5 #include <stdio.h> 6 #include <string.h> 7 #include "ixp_local.h" 8 9 enum { 10 SByte = 1, 11 SWord = 2, 12 SDWord = 4, 13 SQWord = 8, 14 }; 15 16 #define SString(s) (SWord + strlen(s)) 17 enum { 18 SQid = SByte + SDWord + SQWord, 19 }; 20 21 /** 22 * Type: IxpMsg 23 * Type: IxpMsgMode 24 * Function: ixp_message 25 * 26 * The IxpMsg struct represents a binary message, and is used 27 * extensively by libixp for converting messages to and from 28 * wire format. The location and size of a buffer are stored in 29 * P<data> and P<size>, respectively. P<pos> points to the 30 * location in the message currently being packed or unpacked, 31 * while P<end> points to the end of the message. The packing 32 * functions advance P<pos> as they go, always ensuring that 33 * they don't read or write past P<end>. When a message is 34 * entirely packed or unpacked, P<pos> whould be less than or 35 * equal to P<end>. Any other state indicates error. 36 * 37 * ixp_message is a convenience function to pack a construct an 38 * IxpMsg from a buffer of a given P<length> and a given 39 * P<mode>. P<pos> and P<data> are set to P<data> and P<end> is 40 * set to P<data> + P<length>. 41 * 42 * See also: 43 * F<ixp_pu8>, F<ixp_pu16>, F<ixp_pu32>, F<ixp_pu64>, 44 * F<ixp_pstring>, F<ixp_pstrings> 45 */ 46 IxpMsg 47 ixp_message(char *data, uint length, uint mode) { 48 IxpMsg m; 49 50 m.data = data; 51 m.pos = data; 52 m.end = data + length; 53 m.size = length; 54 m.mode = mode; 55 return m; 56 } 57 58 /** 59 * Function: ixp_freestat 60 * Function: ixp_freefcall 61 * 62 * These functions free malloc(3) allocated data in the members 63 * of the passed structures and set those members to nil. They 64 * do not free the structures themselves. 65 * 66 * See also: 67 * S<IxpFcall>, S<IxpStat> 68 */ 69 void 70 ixp_freestat(IxpStat *s) { 71 free(s->name); 72 free(s->uid); 73 free(s->gid); 74 free(s->muid); 75 s->name = s->uid = s->gid = s->muid = nil; 76 } 77 78 void 79 ixp_freefcall(IxpFcall *fcall) { 80 switch(fcall->hdr.type) { 81 case RStat: 82 free(fcall->rstat.stat); 83 fcall->rstat.stat = nil; 84 break; 85 case RRead: 86 free(fcall->rread.data); 87 fcall->rread.data = nil; 88 break; 89 case RVersion: 90 free(fcall->version.version); 91 fcall->version.version = nil; 92 break; 93 case RError: 94 free(fcall->error.ename); 95 fcall->error.ename = nil; 96 break; 97 } 98 } 99 100 uint16_t 101 ixp_sizeof_stat(IxpStat *stat) { 102 return SWord /* size */ 103 + SWord /* type */ 104 + SDWord /* dev */ 105 + SQid /* qid */ 106 + 3 * SDWord /* mode, atime, mtime */ 107 + SQWord /* length */ 108 + SString(stat->name) 109 + SString(stat->uid) 110 + SString(stat->gid) 111 + SString(stat->muid); 112 } 113 114 void 115 ixp_pfcall(IxpMsg *msg, IxpFcall *fcall) { 116 ixp_pu8(msg, &fcall->hdr.type); 117 ixp_pu16(msg, &fcall->hdr.tag); 118 119 switch (fcall->hdr.type) { 120 case TVersion: 121 case RVersion: 122 ixp_pu32(msg, &fcall->version.msize); 123 ixp_pstring(msg, &fcall->version.version); 124 break; 125 case TAuth: 126 ixp_pu32(msg, &fcall->tauth.afid); 127 ixp_pstring(msg, &fcall->tauth.uname); 128 ixp_pstring(msg, &fcall->tauth.aname); 129 break; 130 case RAuth: 131 ixp_pqid(msg, &fcall->rauth.aqid); 132 break; 133 case RAttach: 134 ixp_pqid(msg, &fcall->rattach.qid); 135 break; 136 case TAttach: 137 ixp_pu32(msg, &fcall->hdr.fid); 138 ixp_pu32(msg, &fcall->tattach.afid); 139 ixp_pstring(msg, &fcall->tattach.uname); 140 ixp_pstring(msg, &fcall->tattach.aname); 141 break; 142 case RError: 143 ixp_pstring(msg, &fcall->error.ename); 144 break; 145 case TFlush: 146 ixp_pu16(msg, &fcall->tflush.oldtag); 147 break; 148 case TWalk: 149 ixp_pu32(msg, &fcall->hdr.fid); 150 ixp_pu32(msg, &fcall->twalk.newfid); 151 ixp_pstrings(msg, &fcall->twalk.nwname, fcall->twalk.wname, nelem(fcall->twalk.wname)); 152 break; 153 case RWalk: 154 ixp_pqids(msg, &fcall->rwalk.nwqid, fcall->rwalk.wqid, nelem(fcall->rwalk.wqid)); 155 break; 156 case TOpen: 157 ixp_pu32(msg, &fcall->hdr.fid); 158 ixp_pu8(msg, &fcall->topen.mode); 159 break; 160 case ROpen: 161 case RCreate: 162 ixp_pqid(msg, &fcall->ropen.qid); 163 ixp_pu32(msg, &fcall->ropen.iounit); 164 break; 165 case TCreate: 166 ixp_pu32(msg, &fcall->hdr.fid); 167 ixp_pstring(msg, &fcall->tcreate.name); 168 ixp_pu32(msg, &fcall->tcreate.perm); 169 ixp_pu8(msg, &fcall->tcreate.mode); 170 break; 171 case TRead: 172 ixp_pu32(msg, &fcall->hdr.fid); 173 ixp_pu64(msg, &fcall->tread.offset); 174 ixp_pu32(msg, &fcall->tread.count); 175 break; 176 case RRead: 177 ixp_pu32(msg, &fcall->rread.count); 178 ixp_pdata(msg, &fcall->rread.data, fcall->rread.count); 179 break; 180 case TWrite: 181 ixp_pu32(msg, &fcall->hdr.fid); 182 ixp_pu64(msg, &fcall->twrite.offset); 183 ixp_pu32(msg, &fcall->twrite.count); 184 ixp_pdata(msg, &fcall->twrite.data, fcall->twrite.count); 185 break; 186 case RWrite: 187 ixp_pu32(msg, &fcall->rwrite.count); 188 break; 189 case TClunk: 190 case TRemove: 191 case TStat: 192 ixp_pu32(msg, &fcall->hdr.fid); 193 break; 194 case RStat: 195 ixp_pu16(msg, &fcall->rstat.nstat); 196 ixp_pdata(msg, (char**)&fcall->rstat.stat, fcall->rstat.nstat); 197 break; 198 case TWStat: { 199 uint16_t size; 200 ixp_pu32(msg, &fcall->hdr.fid); 201 ixp_pu16(msg, &size); 202 ixp_pstat(msg, &fcall->twstat.stat); 203 break; 204 } 205 } 206 } 207 208 /** 209 * Function: ixp_fcall2msg 210 * Function: ixp_msg2fcall 211 * 212 * These functions pack or unpack a 9P protocol message. The 213 * message is set to the appropriate mode and its position is 214 * set to the begining of its buffer. 215 * 216 * Returns: 217 * These functions return the size of the message on 218 * success and 0 on failure. 219 * See also: 220 * F<IxpMsg>, F<ixp_pfcall> 221 */ 222 uint 223 ixp_fcall2msg(IxpMsg *msg, IxpFcall *fcall) { 224 uint32_t size; 225 226 msg->end = msg->data + msg->size; 227 msg->pos = msg->data + SDWord; 228 msg->mode = MsgPack; 229 ixp_pfcall(msg, fcall); 230 231 if(msg->pos > msg->end) 232 return 0; 233 234 msg->end = msg->pos; 235 size = msg->end - msg->data; 236 237 msg->pos = msg->data; 238 ixp_pu32(msg, &size); 239 240 msg->pos = msg->data; 241 return size; 242 } 243 244 uint 245 ixp_msg2fcall(IxpMsg *msg, IxpFcall *fcall) { 246 msg->pos = msg->data + SDWord; 247 msg->mode = MsgUnpack; 248 ixp_pfcall(msg, fcall); 249 250 if(msg->pos > msg->end) 251 return 0; 252 253 return msg->pos - msg->data; 254 } 255