/* ca c'est la struct qu'on veut balancer sur le network */ struct passwd { char *pw_name; char *pw_whatever; int uid; int gid; float blabla; }; /* ca c'est la structure qui permet de definir la "gueule" des member */ /* d'une strucure comme celle de la `struct passwd' */ struct definition_member { int type; int offset; char *member_name; }; /* voila un #define par type de membre */ #define TYPE_CHARETOILE 1 #define TYPE_INT32 2 #define TYPE_FLOAT 3 /* ====== BEGIN ONE-BY-NETWORKCALL ===== */ /* voila la structure qui definit le layout de la `struct passwd' et permet */ /* de l'UNPACK, GENEREE PAR UN MAKENETWORKCALL.SH */ struct definition_member gl_passwd_def[] = { {TYPE_CHARETOILE, &((struct passwd *)0)->pw_name, "pw_name"}, {TYPE_CHARETOILE, &((struct passwd *)0)->pw_whatever, "pw_whatever"}, {TYPE_INT32, &((struct passwd *)0)->uid, "uid"}, {TYPE_INT32, &((struct passwd *)0)->gid, "gid"}, {TYPE_FLOAT, &((struct passwd *)0)->blabla, "blabla"} }; /* ====== END ONE-BY-NETWORKCALL ===== */ /* voila le typedef d'une fonction d'unpackage (une par type de membre) */ typedef void (f_unpackfunc)(); /* voila le tableau de pointeur sur function de fonctions qui unpacke la struct */ struct unpack_func { int type; f_unpackfunc *f; }; struct unpack_func gl_unpackfunc[] = { {TYPE_CHARETOILE, unpack_charetoile}, {TYPE_INT32, unpack_int32}, {TYPE_FLOAT, unpack_float} }; /* voila le tableau de networkcall utilise par le serveur (NC means networkcall) */ typedef void (f_handle)(struct networkcall *nc); struct networkcall { int network_call_number; f_handle *f; struct definition_member *def; int definition_size_i_want_to_mean_number_of_element_see_the_sizeof_below; } #define NC_PASSWD 1 /* syscall^Wnetworkcallnumber of passwd request */ #define NC_PASSWD 42_OR_THE_ANSWER /* what you want is what you get? */ struct networkcall gl_networkcall[] = { {NC_PASSWD, handle_passwd, &gl_passwd_def, sizeof(gl_passwd_def}/sizeof(struct definition_member)}, {NC_WHATEVER, handle_otherthings, &gl_whatever_def, sizeof(gl_whatever_def)/sizeof(struct definition_member)} } /* gl_whatever_def (array of type struct definition member is here for purpose exemple)*/ /* et voila les handles */ void handle_otherthings(struct networkcall *nc) { /* do nothing */ } void handle_passwd(struct networkcall *nc) { struct passwd *pw; pw = unpack_payload_from_network_call(nc); } /* THE MAGIC UNPACK FUNCTION */ void *unpack_payload_from_network_call(struct networkcall *nc) { /* OK, so */ /* this function has a struct networkcall corresponding to the NC number in arg */ /* and this struct networkcall gives a way to loop over struct passwd by theirs names */ /* and the struct generated by the makenetworkcall.sh gives the member names */ /* and also their types and handler */ /* just have your pack/unpacking fonction for each member type doing the same job! */ /* (ie. pop in reverse order of the push etc...) */ } /* ====== ANNEXE ====== */ /* si il n'y avait pas d'arguments au networkcall "whaterver", voila ses structures: */ struct whatever { }; struct definition_member gl_whatever[] = { }; /* EMPTY because noargs */ /* === AVANTAGES === */ /* -1) juste transmettre les reals datas sur le network, NE PAS transmettre le layout avec */ /* -2) limite les buffers overflows cote client et serveur grace au pack/unpack */ /* -3) simplicite d'utilisation (pas de programmation :/) */ /* === DISAVANTAGES === */ /* -1) maybe add a big overload to do this type of data processing, eh if you prefer speed */ /* to security, i don't give a shit to your os */ /* ===== ADVANCED TOPICS ==== */ /* Je propose de stocker dans les pointeurs dans une structure, l'offset du payload, par exemple */ /* stocker dans le membre pw_name de la struct passwd, l'offset du payload ou y'a le char* */ /* Quid d'une autre structure dans la structure passwd? need recursive abilities? or forbid complex types? */ /* La methode de pack/unpack de cette embedded-structure pourrait juste etre realisee par un autre */ /* apell a [un]pack_payload_from/to_network_call(), avec pop dans l'ordre inverse du push... */ /* GARDER a l'esprit le concept du networkcall.master derive du bsd syscall.master avec son makesyscall.sh */