openblt

a hobby OS from the late 90s
git clone http://frotz.net/git/openblt.git
Log | Files | Refs | LICENSE

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