use XXX_SOURCE_DIR
[PxpRpc.git] / c / pxprpc / server.c
blobc9faa35775d102a18700e5b59273b8e6a5059abf
3 #include "def.h"
4 #include "config.h"
5 #include <stdint.h>
6 #include <string.h>
7 #include <stdlib.h>
8 #include <memory.h>
10 #include "server.h"
12 #ifdef USE_PTHREAD_HEADER
13 #include <pthread.h>
14 #endif
16 #define MACRO_TO_STR(x) #x
17 #define MACRO_TO_STR2(s) MACRO_TO_STR(s)
20 static const char *ServerInfo="server name:pxprpc for c\n"
21 "version:1.0\n"
22 "reference slots size:" MACRO_TO_STR2(MAX_REFSLOTS_COUNT)"\n";
26 static uint32_t _pxprpc__ref_AddRef(struct pxprpc_object *ref){
27 ref->count++;
28 return ref->count;
31 static uint32_t _pxprpc__ref_Release(struct pxprpc_object *ref){
32 ref->count--;
33 if(ref->count==0){
34 pxprpc__free(ref);
35 return 0;
36 }else{
37 return ref->count;
41 static uint32_t _pxprpc__ref_bytes_Release(struct pxprpc_object *ref){
42 void *bytes=ref->object1;
43 if(ref->count==1){
44 pxprpc__free(bytes);
46 return _pxprpc__ref_Release(ref);
49 static struct pxprpc_object *pxprpc_new_object(void *obj){
50 struct pxprpc_object *ref=pxprpc__malloc(sizeof(struct pxprpc_object));
51 ref->addRef=&_pxprpc__ref_AddRef;
52 ref->release=&_pxprpc__ref_Release;
53 ref->count=0;
54 ref->object1=obj;
55 return ref;
58 static struct pxprpc_object *pxprpc_new_bytes_object(uint32_t size){
59 struct pxprpc_object *ref=pxprpc_new_object(pxprpc__malloc(size+4));
60 ref->type=1;
61 *((int *)(ref->object1))=size;
62 ref->release=_pxprpc__ref_bytes_Release;
63 return ref;
66 static void pxprpc_fill_bytes_object(struct pxprpc_object *obj,uint8_t *data,int size){
67 struct pxprpc_bytes * bytes=(struct pxprpc_bytes *)obj->object1;
68 if(size>bytes->length){
69 size=bytes->length;
71 memcpy(&bytes->data,data,size);
74 struct _pxprpc__ServCo{
75 #pragma pack(1)
76 union{
77 struct{
78 uint32_t session;
79 uint32_t addr1;
80 union{
81 uint32_t addr2;
82 uint32_t length1;
84 } hdr;
85 uint8_t hdrbuf[16];
87 #pragma pack()
88 struct pxprpc_abstract_io *io1;
89 struct pxprpc_object **refSlots;
90 int slotMaxHashOffset;
91 int slotsSize;
92 struct pxprpc_object *t1;
93 pthread_mutex_t writeMutex;
94 int lengthOfNamedFuncs;
95 struct pxprpc_namedfunc *namedfuncs;
96 uint32_t status;
97 uint8_t writeBuf[4];
100 #define _pxprpc__ServCoIsClosed(self) self->status&0x1
102 static int pxprpc_closed(void *server_context){
103 return _pxprpc__ServCoIsClosed(((struct _pxprpc__ServCo*)server_context));
106 static int pxprpc_close(pxprpc_server_context server_context){
107 if(pxprpc_closed(server_context)){
108 return 0;
110 struct _pxprpc__ServCo *self=server_context;
111 for(int i=0;i<MAX_REFSLOTS_COUNT;i++){
112 if(self->refSlots[i]!=NULL){
113 self->refSlots[i]->release(self->refSlots[i]);
116 self->status|=0x1;
117 pxprpc__free(self->refSlots);
118 return 0;
122 static void _pxprpc__step1(struct _pxprpc__ServCo *self);
124 static void _pxprpc__ServCoStart(struct _pxprpc__ServCo *self){
125 self->slotsSize=MAX_REFSLOTS_COUNT;
126 self->refSlots=pxprpc__malloc(sizeof(struct pxprpc_object)*MAX_REFSLOTS_COUNT);
127 memset(self->refSlots,0,sizeof(struct pxprpc_object)*MAX_REFSLOTS_COUNT);
128 pthread_mutex_init(&self->writeMutex,NULL);
129 self->status=0;
130 _pxprpc__step1(self);
133 static void _pxprpc__RefSlotsPut(struct _pxprpc__ServCo *self,uint32_t addr, struct pxprpc_object *ref2){
134 struct pxprpc_object *ref=self->refSlots[addr];
135 if(ref!=NULL){
136 ref->release(ref);
138 if(ref2!=NULL){
139 ref2->addRef(ref2);
141 self->refSlots[addr]=ref2;
144 static void _pxprpc__nopcallback(void *p){}
146 //Push handler
147 static void _pxprpc__stepPush3(struct _pxprpc__ServCo *self){
148 if(self->io1->get_error(self->io1,self->io1->read)!=NULL)return;
149 _pxprpc__RefSlotsPut(self,self->hdr.addr1,self->t1);
150 pthread_mutex_lock(&self->writeMutex);
151 self->io1->write(self->io1,4,(uint8_t *)&self->hdr.session,(void (*)(void *))_pxprpc__step1,self);
152 pthread_mutex_unlock(&self->writeMutex);
154 static void _pxprpc__stepPush2(struct _pxprpc__ServCo *self){
155 if(self->io1->get_error(self->io1,self->io1->read)!=NULL)return;
156 self->t1=pxprpc_new_bytes_object(self->hdr.length1);
158 self->io1->read(self->io1,self->hdr.length1,((struct pxprpc_bytes *)self->t1->object1)->data,
159 (void (*)(void *))&_pxprpc__stepPush3,self);
161 static void _pxprpc__stepPush1(struct _pxprpc__ServCo *self){
162 self->io1->read(self->io1,8,(uint8_t*)&self->hdr.addr1,(void (*)(void *))&_pxprpc__stepPush2,self);
165 //Pull handler
166 static void _pxprpc__stepPull2(struct _pxprpc__ServCo *self){
167 if(self->io1->get_error(self->io1,self->io1->read)!=NULL)return;
168 int destAddr=self->hdr.addr1;
170 struct pxprpc_bytes *bytes=self->refSlots[destAddr]->object1;
172 pthread_mutex_lock(&self->writeMutex);
173 self->io1->write(self->io1,4,(uint8_t *)&self->hdr.session,_pxprpc__nopcallback,NULL);
174 if(bytes!=NULL){
175 self->io1->write(self->io1,4,(uint8_t *)&bytes->length,_pxprpc__nopcallback,NULL);
176 self->io1->write(self->io1,bytes->length,bytes->data,(void (*)(void *))_pxprpc__step1,self);
177 }else{
178 *(uint32_t *)(&self->writeBuf)=0xffffffff;
179 self->io1->write(self->io1,4,self->writeBuf,(void (*)(void *))_pxprpc__step1,self);
181 pthread_mutex_unlock(&self->writeMutex);
183 static void _pxprpc__stepPull1(struct _pxprpc__ServCo *self){
184 self->io1->read(self->io1,4,(uint8_t*)&self->hdr.addr1,(void (*)(void *))&_pxprpc__stepPull2,self);
187 //Assign handler
188 static void _pxprpc__stepAssign2(struct _pxprpc__ServCo *self){
189 if(self->io1->get_error(self->io1,self->io1->read)!=NULL)return;
190 _pxprpc__RefSlotsPut(self,self->hdr.addr1,self->refSlots[self->hdr.addr2]);
191 pthread_mutex_lock(&self->writeMutex);
192 self->io1->write(self->io1,4,(uint8_t *)&self->hdr.session,(void (*)(void *))_pxprpc__step1,self);
193 pthread_mutex_unlock(&self->writeMutex);
195 static void _pxprpc__stepAssign1(struct _pxprpc__ServCo *self){
196 self->io1->read(self->io1,8,(uint8_t*)&self->hdr.addr1,(void (*)(void *))&_pxprpc__stepAssign2,self);
200 //Unlink handler
201 static void _pxprpc__stepUnlink2(struct _pxprpc__ServCo *self){
202 if(self->io1->get_error(self->io1,self->io1->read)!=NULL)return;
203 _pxprpc__RefSlotsPut(self,self->hdr.addr1,NULL);
204 pthread_mutex_lock(&self->writeMutex);
205 self->io1->write(self->io1,4,(uint8_t *)&self->hdr.session,(void (*)(void *))_pxprpc__step1,self);
206 pthread_mutex_unlock(&self->writeMutex);
208 static void _pxprpc__stepUnlink1(struct _pxprpc__ServCo *self){
209 self->io1->read(self->io1,4,(uint8_t*)&self->hdr.addr1,(void (*)(void *))&_pxprpc__stepUnlink2,self);
212 //Call Handler
213 static void _pxprpc__stepCall4(struct pxprpc_request *r, struct pxprpc_object *result){
214 struct _pxprpc__ServCo *self=r->server_context;
215 _pxprpc__RefSlotsPut(r->server_context,r->dest_addr,result);
216 r->result=result;
217 pthread_mutex_lock(&self->writeMutex);
218 self->io1->write(self->io1,4,(uint8_t *)&r->session,_pxprpc__nopcallback,NULL);
219 r->callable->writeResult(r->callable,r);
220 pthread_mutex_unlock(&self->writeMutex);
221 pxprpc__free(r);
224 static void _pxprpc__stepCall3(struct pxprpc_request *r){
225 struct _pxprpc__ServCo *self=(struct _pxprpc__ServCo *)r->server_context;
226 r->callable->call(r->callable,r,&_pxprpc__stepCall4);
227 _pxprpc__step1(self);
229 static void _pxprpc__stepCall2(struct _pxprpc__ServCo *self){
230 if(self->io1->get_error(self->io1,self->io1->read)!=NULL)return;
231 struct pxprpc_request *req=(struct pxprpc_request *)pxprpc__malloc(sizeof(struct pxprpc_request));
232 req->session=self->hdr.session;
233 req->io1=self->io1;
234 req->ref_slots=self->refSlots;
235 req->dest_addr=self->hdr.addr1;
236 req->server_context=self;
237 struct pxprpc_callable *func=(struct pxprpc_callable *)((struct pxprpc_object *)self->refSlots[self->hdr.addr2])->object1;
238 req->callable=func;
239 func->readParameter(func,req,&_pxprpc__stepCall3);
241 static void _pxprpc__stepCall1(struct _pxprpc__ServCo *self){
242 self->io1->read(self->io1,8,(uint8_t*)&self->hdr.addr1,(void (*)(void *))&_pxprpc__stepCall2,self);
245 //str1(2)Len = -1 indicate 0-ending string, In this case the real length will be put into *str1(2)Len after function return.
246 //string length is limited to 0x1000
247 static int _pxprpc__strcmp2(const char *str1,int *str1Len,const char *str2,int *str2Len){
248 int i,r;
249 if(*str1Len==-1){
250 for(i=0;i<0x1000;i++){
251 if(str1[i]==0){
252 break;
255 *str1Len=i;
257 if(*str2Len==-1){
258 for(i=0;i<0x1000;i++){
259 if(str2[i]==0){
260 break;
263 *str2Len=i;
265 if(*str1Len==*str2Len){
266 for(i=0,r=0;i<*str1Len;i++){
267 if(str1[i]!=str2[i]){
268 r=str1[i]-str2[i];
269 break;
272 }else{
273 r=*str1Len-*str2Len;
275 return r;
277 //GetFunc handler
278 static void _pxprpc__stepGetFunc2(struct _pxprpc__ServCo *self){
279 if(self->io1->get_error(self->io1,self->io1->read)!=NULL)return;
280 struct pxprpc_bytes *bs=(struct pxprpc_bytes *)self->refSlots[self->hdr.addr2]->object1;
281 int returnAddr=0;
282 int lenOut=-1;
283 for(int i=0;i<self->lengthOfNamedFuncs;i++){
284 lenOut=-1;
285 int cmp1=_pxprpc__strcmp2(self->namedfuncs[i].name,&lenOut,(const char *)bs->data,&bs->length);
286 if(!cmp1){
287 _pxprpc__RefSlotsPut(self,self->hdr.addr1,pxprpc_new_object(self->namedfuncs[i].callable));
288 returnAddr=self->hdr.addr1;
289 break;
292 pthread_mutex_lock(&self->writeMutex);
293 *(uint32_t *)(&self->writeBuf)=returnAddr;
294 self->io1->write(self->io1,4,(uint8_t *)&self->hdr.session,_pxprpc__nopcallback,NULL);
295 self->io1->write(self->io1,4,self->writeBuf,(void (*)(void *))_pxprpc__step1,self);
296 pthread_mutex_unlock(&self->writeMutex);
298 static void _pxprpc__stepGetFunc1(struct _pxprpc__ServCo *self){
299 self->io1->read(self->io1,8,(uint8_t*)&self->hdr.addr1,(void(*)(void *))&_pxprpc__stepGetFunc2,self);
303 //Close handler
304 static int _pxprpc__stepClose1(struct _pxprpc__ServCo *self){
305 pxprpc_close(self);
310 //GetInfo handler
311 static void _pxprpc__stepGetInfo1(struct _pxprpc__ServCo *self){
312 pthread_mutex_lock(&self->writeMutex);
313 uint32_t length=strlen(ServerInfo);
314 self->io1->write(self->io1,4,(uint8_t *)&self->hdr.session,_pxprpc__nopcallback,NULL);
315 *(uint32_t *)(&self->writeBuf)=length;
316 self->io1->write(self->io1,4,(uint8_t *)&length,_pxprpc__nopcallback,NULL);
317 self->io1->write(self->io1,length,ServerInfo,(void (*)(void *))_pxprpc__step1,self);
318 pthread_mutex_unlock(&self->writeMutex);
321 #include <stdio.h>
322 static void _pxprpc__step2(struct _pxprpc__ServCo *self){
323 if(self->io1->get_error(self->io1,self->io1->read)!=NULL)return;
324 int opcode=self->hdrbuf[0];
325 switch(opcode){
326 case 1:
327 _pxprpc__stepPush1(self);
328 break;
329 case 2:
330 _pxprpc__stepPull1(self);
331 break;
332 case 3:
333 _pxprpc__stepAssign1(self);
334 break;
335 case 4:
336 _pxprpc__stepUnlink1(self);
337 break;
338 case 5:
339 _pxprpc__stepCall1(self);
340 break;
341 case 6:
342 _pxprpc__stepGetFunc1(self);
343 break;
344 case 7:
345 pxprpc_close(self);
346 break;
347 case 8:
348 _pxprpc__stepGetInfo1(self);
349 break;
353 static void _pxprpc__step1(struct _pxprpc__ServCo *self){
354 if(_pxprpc__ServCoIsClosed(self)){
355 return;
357 self->io1->read(self->io1,4,self->hdrbuf,(void(*)(void *))_pxprpc__step2,self);
362 static int pxprpc_new_server_context(pxprpc_server_context *server_context,struct pxprpc_abstract_io *io1,struct pxprpc_namedfunc *namedfuncs,int len_namedfuncs){
363 struct _pxprpc__ServCo *ctx=(struct _pxprpc__ServCo *)pxprpc__malloc(sizeof(struct _pxprpc__ServCo));
364 memset(ctx,0,sizeof(struct _pxprpc__ServCo));
365 ctx->io1=io1;
366 ctx->namedfuncs=namedfuncs;
367 ctx->lengthOfNamedFuncs=len_namedfuncs;
368 *server_context=ctx;
369 return 0;
372 static int pxprpc_start_serve(pxprpc_server_context server_context){
373 struct _pxprpc__ServCo *ctx=(struct _pxprpc__ServCo *)server_context;
374 _pxprpc__ServCoStart(ctx);
375 return 0;
378 static int pxprpc_free_context(pxprpc_server_context *server_context){
379 struct _pxprpc__ServCo *ctx=(struct _pxprpc__ServCo *)*server_context;
380 pxprpc_close(ctx);
381 pxprpc__free(*server_context);
382 return 0;
386 static pxprpc_server_api exports={
387 &pxprpc_new_server_context,&pxprpc_start_serve,&pxprpc_closed,&pxprpc_close,&pxprpc_free_context,
388 &pxprpc_new_object,&pxprpc_new_bytes_object,&pxprpc_fill_bytes_object
391 extern int pxprpc_server_query_interface(pxprpc_server_api **outapi){
392 *outapi=&exports;