c backend refact, implementing serilizer
[PxpRpc.git] / c / pxprpc / server.c
blobda173de26d21642cc1fc4aecb894ae8eda9a6dc3
3 #include <pxprpc.h>
5 #include <stdint.h>
6 #include <string.h>
7 #include <stdlib.h>
8 #include <memory.h>
11 #ifdef USE_PTHREAD_HEADER
12 #include <pthread.h>
13 #endif
15 #define MACRO_TO_STR(x) #x
16 #define MACRO_TO_STR2(s) MACRO_TO_STR(s)
19 static const char *ServerInfo="server name:pxprpc for c\n"
20 "version:1.0\n"
21 "reference slots size:" MACRO_TO_STR2(MAX_REFSLOTS_COUNT)"\n";
25 static uint32_t _pxprpc__ref_AddRef(struct pxprpc_object *ref){
26 ref->count++;
27 return ref->count;
30 static uint32_t _pxprpc__ref_Release(struct pxprpc_object *ref){
31 ref->count--;
32 if(ref->count==0){
33 pxprpc__free(ref);
34 return 0;
35 }else{
36 return ref->count;
40 static uint32_t _pxprpc__ref_bytes_Release(struct pxprpc_object *ref){
41 void *bytes=ref->object1;
42 if(ref->count==1){
43 pxprpc__free(bytes);
45 return _pxprpc__ref_Release(ref);
48 static struct pxprpc_object *pxprpc_new_object(void *obj){
49 struct pxprpc_object *ref=pxprpc__malloc(sizeof(struct pxprpc_object));
50 ref->addRef=&_pxprpc__ref_AddRef;
51 ref->release=&_pxprpc__ref_Release;
52 ref->count=0;
53 ref->object1=obj;
54 return ref;
57 static struct pxprpc_object *pxprpc_new_bytes_object(uint32_t size){
58 struct pxprpc_object *ref=pxprpc_new_object(pxprpc__malloc(size+4));
59 ref->type=1;
60 *((int *)(ref->object1))=size;
61 ref->release=_pxprpc__ref_bytes_Release;
62 return ref;
65 static void pxprpc_fill_bytes_object(struct pxprpc_object *obj,uint8_t *data,int size){
66 struct pxprpc_bytes * bytes=(struct pxprpc_bytes *)obj->object1;
67 if(size>bytes->length){
68 size=bytes->length;
70 memcpy(&bytes->data,data,size);
73 struct _pxprpc__ServCo{
74 #pragma pack(1)
75 union{
76 struct{
77 uint32_t session;
78 uint32_t addr1;
79 union{
80 uint32_t addr2;
81 uint32_t length1;
83 } hdr;
84 uint8_t hdrbuf[16];
86 #pragma pack()
87 struct pxprpc_abstract_io *io1;
88 struct pxprpc_object **refSlots;
89 int slotMaxHashOffset;
90 int slotsSize;
91 struct pxprpc_object *t1;
92 pthread_mutex_t writeMutex;
93 int lengthOfNamedFuncs;
94 struct pxprpc_namedfunc *namedfuncs;
95 uint32_t status;
96 uint8_t writeBuf[4];
99 #define _pxprpc__ServCoIsClosed(self) self->status&0x1
101 static int pxprpc_closed(void *server_context){
102 return _pxprpc__ServCoIsClosed(((struct _pxprpc__ServCo*)server_context));
105 static int pxprpc_close(pxprpc_server_context server_context){
106 if(pxprpc_closed(server_context)){
107 return 0;
109 struct _pxprpc__ServCo *self=server_context;
110 for(int i=0;i<MAX_REFSLOTS_COUNT;i++){
111 if(self->refSlots[i]!=NULL){
112 self->refSlots[i]->release(self->refSlots[i]);
115 self->status|=0x1;
116 pxprpc__free(self->refSlots);
117 return 0;
121 static void _pxprpc__step1(struct _pxprpc__ServCo *self);
123 static void _pxprpc__ServCoStart(struct _pxprpc__ServCo *self){
124 self->slotsSize=MAX_REFSLOTS_COUNT;
125 self->refSlots=pxprpc__malloc(sizeof(struct pxprpc_object)*MAX_REFSLOTS_COUNT);
126 memset(self->refSlots,0,sizeof(struct pxprpc_object)*MAX_REFSLOTS_COUNT);
127 pthread_mutex_init(&self->writeMutex,NULL);
128 self->status=0;
129 _pxprpc__step1(self);
132 static void _pxprpc__RefSlotsPut(struct _pxprpc__ServCo *self,uint32_t addr, struct pxprpc_object *ref2){
133 struct pxprpc_object *ref=self->refSlots[addr];
134 if(ref!=NULL){
135 ref->release(ref);
137 if(ref2!=NULL){
138 ref2->addRef(ref2);
140 self->refSlots[addr]=ref2;
143 static void _pxprpc__nopcallback(void *p){}
145 //Push handler
146 static void _pxprpc__stepPush3(struct _pxprpc__ServCo *self){
147 if(self->io1->get_error(self->io1,self->io1->read)!=NULL)return;
148 _pxprpc__RefSlotsPut(self,self->hdr.addr1,self->t1);
149 pthread_mutex_lock(&self->writeMutex);
150 self->io1->write(self->io1,4,(uint8_t *)&self->hdr.session,(void (*)(void *))_pxprpc__step1,self);
151 pthread_mutex_unlock(&self->writeMutex);
153 static void _pxprpc__stepPush2(struct _pxprpc__ServCo *self){
154 if(self->io1->get_error(self->io1,self->io1->read)!=NULL)return;
155 self->t1=pxprpc_new_bytes_object(self->hdr.length1);
157 self->io1->read(self->io1,self->hdr.length1,((struct pxprpc_bytes *)self->t1->object1)->data,
158 (void (*)(void *))&_pxprpc__stepPush3,self);
160 static void _pxprpc__stepPush1(struct _pxprpc__ServCo *self){
161 self->io1->read(self->io1,8,(uint8_t*)&self->hdr.addr1,(void (*)(void *))&_pxprpc__stepPush2,self);
164 //Pull handler
165 static void _pxprpc__stepPull2(struct _pxprpc__ServCo *self){
166 if(self->io1->get_error(self->io1,self->io1->read)!=NULL)return;
167 int destAddr=self->hdr.addr1;
169 struct pxprpc_bytes *bytes=self->refSlots[destAddr]->object1;
171 pthread_mutex_lock(&self->writeMutex);
172 self->io1->write(self->io1,4,(uint8_t *)&self->hdr.session,_pxprpc__nopcallback,NULL);
173 if(bytes!=NULL){
174 self->io1->write(self->io1,4,(uint8_t *)&bytes->length,_pxprpc__nopcallback,NULL);
175 self->io1->write(self->io1,bytes->length,bytes->data,(void (*)(void *))_pxprpc__step1,self);
176 }else{
177 *(uint32_t *)(&self->writeBuf)=0xffffffff;
178 self->io1->write(self->io1,4,self->writeBuf,(void (*)(void *))_pxprpc__step1,self);
180 pthread_mutex_unlock(&self->writeMutex);
182 static void _pxprpc__stepPull1(struct _pxprpc__ServCo *self){
183 self->io1->read(self->io1,4,(uint8_t*)&self->hdr.addr1,(void (*)(void *))&_pxprpc__stepPull2,self);
186 //Assign handler
187 static void _pxprpc__stepAssign2(struct _pxprpc__ServCo *self){
188 if(self->io1->get_error(self->io1,self->io1->read)!=NULL)return;
189 _pxprpc__RefSlotsPut(self,self->hdr.addr1,self->refSlots[self->hdr.addr2]);
190 pthread_mutex_lock(&self->writeMutex);
191 self->io1->write(self->io1,4,(uint8_t *)&self->hdr.session,(void (*)(void *))_pxprpc__step1,self);
192 pthread_mutex_unlock(&self->writeMutex);
194 static void _pxprpc__stepAssign1(struct _pxprpc__ServCo *self){
195 self->io1->read(self->io1,8,(uint8_t*)&self->hdr.addr1,(void (*)(void *))&_pxprpc__stepAssign2,self);
199 //Unlink handler
200 static void _pxprpc__stepUnlink2(struct _pxprpc__ServCo *self){
201 if(self->io1->get_error(self->io1,self->io1->read)!=NULL)return;
202 _pxprpc__RefSlotsPut(self,self->hdr.addr1,NULL);
203 pthread_mutex_lock(&self->writeMutex);
204 self->io1->write(self->io1,4,(uint8_t *)&self->hdr.session,(void (*)(void *))_pxprpc__step1,self);
205 pthread_mutex_unlock(&self->writeMutex);
207 static void _pxprpc__stepUnlink1(struct _pxprpc__ServCo *self){
208 self->io1->read(self->io1,4,(uint8_t*)&self->hdr.addr1,(void (*)(void *))&_pxprpc__stepUnlink2,self);
211 //Call Handler
212 static void _pxprpc__stepCall4(struct pxprpc_request *r, struct pxprpc_object *result){
213 struct _pxprpc__ServCo *self=r->server_context;
214 _pxprpc__RefSlotsPut(r->server_context,r->dest_addr,result);
215 r->result=result;
216 pthread_mutex_lock(&self->writeMutex);
217 self->io1->write(self->io1,4,(uint8_t *)&r->session,_pxprpc__nopcallback,NULL);
218 r->callable->writeResult(r->callable,r);
219 pthread_mutex_unlock(&self->writeMutex);
220 pxprpc__free(r);
223 static void _pxprpc__stepCall3(struct pxprpc_request *r){
224 struct _pxprpc__ServCo *self=(struct _pxprpc__ServCo *)r->server_context;
225 r->callable->call(r->callable,r,&_pxprpc__stepCall4);
226 _pxprpc__step1(self);
228 static void _pxprpc__stepCall2(struct _pxprpc__ServCo *self){
229 if(self->io1->get_error(self->io1,self->io1->read)!=NULL)return;
230 struct pxprpc_request *req=(struct pxprpc_request *)pxprpc__malloc(sizeof(struct pxprpc_request));
231 req->session=self->hdr.session;
232 req->io1=self->io1;
233 req->ref_slots=self->refSlots;
234 req->dest_addr=self->hdr.addr1;
235 req->server_context=self;
236 struct pxprpc_callable *func=(struct pxprpc_callable *)((struct pxprpc_object *)self->refSlots[self->hdr.addr2])->object1;
237 req->callable=func;
238 func->readParameter(func,req,&_pxprpc__stepCall3);
240 static void _pxprpc__stepCall1(struct _pxprpc__ServCo *self){
241 self->io1->read(self->io1,8,(uint8_t*)&self->hdr.addr1,(void (*)(void *))&_pxprpc__stepCall2,self);
244 //str1(2)Len = -1 indicate 0-ending string, In this case the real length will be put into *str1(2)Len after function return.
245 //string length is limited to 0x1000
246 static int _pxprpc__strcmp2(const char *str1,int *str1Len,const char *str2,int *str2Len){
247 int i,r;
248 if(*str1Len==-1){
249 for(i=0;i<0x1000;i++){
250 if(str1[i]==0){
251 break;
254 *str1Len=i;
256 if(*str2Len==-1){
257 for(i=0;i<0x1000;i++){
258 if(str2[i]==0){
259 break;
262 *str2Len=i;
264 if(*str1Len==*str2Len){
265 for(i=0,r=0;i<*str1Len;i++){
266 if(str1[i]!=str2[i]){
267 r=str1[i]-str2[i];
268 break;
271 }else{
272 r=*str1Len-*str2Len;
274 return r;
276 //GetFunc handler
277 static void _pxprpc__stepGetFunc2(struct _pxprpc__ServCo *self){
278 if(self->io1->get_error(self->io1,self->io1->read)!=NULL)return;
279 struct pxprpc_bytes *bs=(struct pxprpc_bytes *)self->refSlots[self->hdr.addr2]->object1;
280 int returnAddr=0;
281 int lenOut=-1;
282 for(int i=0;i<self->lengthOfNamedFuncs;i++){
283 lenOut=-1;
284 int cmp1=_pxprpc__strcmp2(self->namedfuncs[i].name,&lenOut,(const char *)bs->data,&bs->length);
285 if(!cmp1){
286 _pxprpc__RefSlotsPut(self,self->hdr.addr1,pxprpc_new_object(self->namedfuncs[i].callable));
287 returnAddr=self->hdr.addr1;
288 break;
291 pthread_mutex_lock(&self->writeMutex);
292 *(uint32_t *)(&self->writeBuf)=returnAddr;
293 self->io1->write(self->io1,4,(uint8_t *)&self->hdr.session,_pxprpc__nopcallback,NULL);
294 self->io1->write(self->io1,4,self->writeBuf,(void (*)(void *))_pxprpc__step1,self);
295 pthread_mutex_unlock(&self->writeMutex);
297 static void _pxprpc__stepGetFunc1(struct _pxprpc__ServCo *self){
298 self->io1->read(self->io1,8,(uint8_t*)&self->hdr.addr1,(void(*)(void *))&_pxprpc__stepGetFunc2,self);
302 //Close handler
303 static int _pxprpc__stepClose1(struct _pxprpc__ServCo *self){
304 pxprpc_close(self);
309 //GetInfo handler
310 static void _pxprpc__stepGetInfo1(struct _pxprpc__ServCo *self){
311 pthread_mutex_lock(&self->writeMutex);
312 uint32_t length=strlen(ServerInfo);
313 self->io1->write(self->io1,4,(uint8_t *)&self->hdr.session,_pxprpc__nopcallback,NULL);
314 *(uint32_t *)(&self->writeBuf)=length;
315 self->io1->write(self->io1,4,(uint8_t *)&length,_pxprpc__nopcallback,NULL);
316 self->io1->write(self->io1,length,ServerInfo,(void (*)(void *))_pxprpc__step1,self);
317 pthread_mutex_unlock(&self->writeMutex);
320 #include <stdio.h>
321 static void _pxprpc__step2(struct _pxprpc__ServCo *self){
322 if(self->io1->get_error(self->io1,self->io1->read)!=NULL)return;
323 int opcode=self->hdrbuf[0];
324 switch(opcode){
325 case 1:
326 _pxprpc__stepPush1(self);
327 break;
328 case 2:
329 _pxprpc__stepPull1(self);
330 break;
331 case 3:
332 _pxprpc__stepAssign1(self);
333 break;
334 case 4:
335 _pxprpc__stepUnlink1(self);
336 break;
337 case 5:
338 _pxprpc__stepCall1(self);
339 break;
340 case 6:
341 _pxprpc__stepGetFunc1(self);
342 break;
343 case 7:
344 pxprpc_close(self);
345 break;
346 case 8:
347 _pxprpc__stepGetInfo1(self);
348 break;
352 static void _pxprpc__step1(struct _pxprpc__ServCo *self){
353 if(_pxprpc__ServCoIsClosed(self)){
354 return;
356 self->io1->read(self->io1,4,self->hdrbuf,(void(*)(void *))_pxprpc__step2,self);
361 static int pxprpc_new_server_context(pxprpc_server_context *server_context,struct pxprpc_abstract_io *io1,struct pxprpc_namedfunc *namedfuncs,int len_namedfuncs){
362 struct _pxprpc__ServCo *ctx=(struct _pxprpc__ServCo *)pxprpc__malloc(sizeof(struct _pxprpc__ServCo));
363 memset(ctx,0,sizeof(struct _pxprpc__ServCo));
364 ctx->io1=io1;
365 ctx->namedfuncs=namedfuncs;
366 ctx->lengthOfNamedFuncs=len_namedfuncs;
367 *server_context=ctx;
368 return 0;
371 static int pxprpc_start_serve(pxprpc_server_context server_context){
372 struct _pxprpc__ServCo *ctx=(struct _pxprpc__ServCo *)server_context;
373 _pxprpc__ServCoStart(ctx);
374 return 0;
377 static int pxprpc_free_context(pxprpc_server_context *server_context){
378 struct _pxprpc__ServCo *ctx=(struct _pxprpc__ServCo *)*server_context;
379 pxprpc_close(ctx);
380 pxprpc__free(*server_context);
381 return 0;
385 static pxprpc_server_api exports={
386 &pxprpc_new_server_context,&pxprpc_start_serve,&pxprpc_closed,&pxprpc_close,&pxprpc_free_context,
387 &pxprpc_new_object,&pxprpc_new_bytes_object,&pxprpc_fill_bytes_object
390 extern int pxprpc_server_query_interface(pxprpc_server_api **outapi){
391 *outapi=&exports;