Message.cpp (5370B)
1 // Copyright 1999, Brian J. Swetland. All Rights Reserved. 2 // This file is provided under the terms of the OpenBLT License 3 4 #include <stdlib.h> 5 #include <string.h> 6 7 #include <blt/Message.h> 8 #include <blt/syscall.h> 9 10 #define GROW_BY 128 11 #define BLT_ID_MESSAGE 0x42023017 12 13 using namespace BLT; 14 15 struct chunk 16 { 17 uint32 type; 18 uint32 id; 19 uint32 len; 20 uchar data[4]; 21 }; 22 23 Message::Message() 24 { 25 chunk *c; 26 27 _data = malloc(GROW_BY); 28 _length = 12; 29 _available = GROW_BY - 12; 30 31 c = (chunk*) _data; 32 33 c->type = BLT_TYPE_MESSAGE; 34 c->id = BLT_ID_MESSAGE; 35 c->len = 0; 36 37 _reply_port = 0; 38 } 39 40 41 Message::~Message() 42 { 43 if(_data) free(_data); 44 } 45 46 int 47 Message::PutData(uint32 type, uint32 id, const void *data, uint32 len) 48 { 49 chunk *c; 50 uint32 size = 12 + ((len + 3) & ~3); 51 52 if(_available < size) { 53 while(_available < size) { 54 _available += GROW_BY; 55 } 56 _data = realloc(_data, (_length + _available)); 57 } 58 59 c = (chunk*) ((char*) _data + _length); 60 c->type = type; 61 c->id = id; 62 c->len = len; 63 memcpy(c->data, data, len); 64 65 _length += size; 66 ((chunk*)_data)->len = _length - 12; 67 } 68 69 int 70 Message::GetData(uint32 type, uint32 id, void *data, uint32 len) const 71 { 72 chunk *c; 73 char *x = (char *) _data + 12; 74 uint32 count = _length - 12; 75 uint32 size; 76 77 while(count > 12){ 78 c = (chunk*) x; 79 size = (12 + ((c->len + 3) & ~3)); 80 if((type == c->type) && (id == c->id) && (len == c->len)){ 81 memcpy(data, c->data, c->len); 82 return 0; 83 } 84 85 x += size; 86 count -= size; 87 } 88 89 return -1; 90 } 91 92 int 93 Message::GetData(uint32 type, uint32 id, const void **data, uint32 *len) const 94 { 95 chunk *c; 96 char *x = (char *) _data + 12; 97 uint32 count = _length - 12; 98 uint32 size; 99 100 while(count > 12){ 101 c = (chunk*) x; 102 size = (12 + ((c->len + 3) & ~3)); 103 if((type == c->type) && (id == c->id)){ 104 *data = (void*) c->data; 105 *len = c->len; 106 return 0; 107 } 108 109 x += size; 110 count -= size; 111 } 112 113 *data = NULL; 114 return -1; 115 } 116 117 int 118 Message::GetEntry(uint32 n, uint32 *type, uint32 *id, const void **data, uint32 *len) const 119 { 120 chunk *c; 121 char *x = (char *) _data + 12; 122 uint32 count = _length - 12; 123 uint32 size; 124 uint32 _n = 0; 125 126 while(count > 12){ 127 c = (chunk*) x; 128 if(_n == n){ 129 *type = c->type; 130 *id = c->id; 131 *len = c->len; 132 *data = (void*) c->data; 133 } 134 135 size = (12 + ((c->len + 3) & 3)); 136 x += size; 137 count -= size; 138 } 139 140 *data = NULL; 141 return -1; 142 } 143 144 int 145 Message::GetPackedData(const void **data, uint32 *length) const 146 { 147 *data = _data; 148 *length = _length; 149 150 return 0; 151 } 152 153 int 154 Message::PutPackedData(const void *data, uint32 length, int reply_port) 155 { 156 chunk *c = (chunk*) data; 157 158 if(length < 12) return -1; 159 160 if(c->type != BLT_TYPE_MESSAGE) return -1; 161 if(c->id != BLT_ID_MESSAGE) return -1; 162 if(c->len != (length - 12)) return -1; 163 164 if(_data) free(_data); 165 _data = malloc(length); 166 167 memcpy(_data, data, length); 168 _available = 0; 169 _length = length; 170 171 _reply_port = reply_port; 172 173 return 0; 174 } 175 176 int 177 Message::PutInt32(uint32 id, int32 data) 178 { 179 return PutData(BLT_TYPE_INT32, id, &data, sizeof(int32)); 180 } 181 182 int 183 Message::PutString(uint32 id, const char *data) 184 { 185 return PutData(BLT_TYPE_STRING, id, data, strlen(data)+1); 186 } 187 188 int 189 Message::PutPointer(uint32 id, void *data) 190 { 191 return PutData(BLT_TYPE_POINTER, id, data, sizeof(void*)); 192 } 193 194 int 195 Message::PutMessage(uint32 id, Message *msg) 196 { 197 return PutData(BLT_TYPE_MESSAGE, id, msg->_data, msg->_length); 198 } 199 200 int 201 Message::GetInt32(uint32 id, int32 *data) const 202 { 203 return GetData(BLT_TYPE_INT32, id, (void*) data, sizeof(int32)); 204 } 205 206 int 207 Message::GetString(uint32 id, const char **data) const 208 { 209 uint32 discard; 210 return GetData(BLT_TYPE_STRING, id, (const void**) data, &discard); 211 } 212 213 int 214 Message::GetPointer(uint32 id, void **ptr) const 215 { 216 return GetData(BLT_TYPE_POINTER, id, (void*) ptr, sizeof(void *)); 217 } 218 219 int 220 Message::GetMessage(uint32 id, Message *msg) const 221 { 222 const void *data; 223 uint32 len; 224 225 GetData(BLT_TYPE_MESSAGE, id, &data, &len); 226 return msg->PutPackedData(data,len); 227 } 228 229 void 230 Message::Empty() 231 { 232 _available += _length - 12; 233 _length = 12; 234 _reply_port = 0; 235 ((chunk*)_data)->len = 0; 236 } 237 238 int 239 Message::Reply(const Message *msg) const 240 { 241 msg_hdr_t mh; 242 int res; 243 244 if(_reply_port > 0){ 245 if((res = port_create(0,"reply_port")) < 0) return res; 246 mh.flags = 0; 247 mh.src = res; 248 mh.dst = _reply_port; 249 mh.size = msg->_length; 250 mh.data = msg->_data; 251 res = old_port_send(&mh); 252 port_destroy(mh.src); 253 if(res == msg->_length) { 254 return 0; 255 } else { 256 return res; 257 } 258 } else { 259 return -1; 260 } 261 } 262 263 #if 0 264 265 void Message::dump() 266 { 267 int i,j; 268 fprintf(stderr,"bMessage - %d of %d\n",_length,_length+_available); 269 270 for(i=0;i<_length;i+=16){ 271 fprintf(stderr,"%04x: ",i); 272 for(j=0;j<16;j++){ 273 if((i+j) < _length){ 274 fprintf(stderr,"%02x ",((uchar*)_data)[i+j]); 275 } else { 276 fprintf(stderr," "); 277 } 278 } 279 fprintf(stderr," "); 280 for(j=0;j<16;j++){ 281 if((i+j) < _length){ 282 uchar c = ((uchar*)_data)[i+j]; 283 if((c<' ')||(c>126)) c = '.'; 284 fprintf(stderr,"%c",c); 285 } else { 286 fprintf(stderr," "); 287 } 288 } 289 fprintf(stderr,"\n"); 290 } 291 292 } 293 294 int main(int argc, char *argv[]) 295 { 296 int32 n; 297 const char *s; 298 299 Message msg; 300 msg.PutInt32('foob',42); 301 msg.PutString('blah',"Hello, Message"); 302 303 if(msg.GetInt32('foob',&n)) exit(1); 304 fprintf(stderr,"foob = %d\n",n); 305 306 if(msg.GetString('blah',&s)) exit(1); 307 fprintf(stderr,"blah = %s\n",s); 308 309 msg.dump(); 310 return 0; 311 } 312 #endif