[examples] smpfd added stream, few functions;
This commit is contained in:
		
							parent
							
								
									8b20f8989f
								
							
						
					
					
						commit
						60e676a979
					
				| @ -62,3 +62,56 @@ int openlistener_socket(int port) | |||||||
|   return sd; |   return sd; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | char *nodehostname(void) | ||||||
|  | { | ||||||
|  |   char *hm = malloc(HOST_NAME_MAX); | ||||||
|  | 
 | ||||||
|  |   if(!gethostname(hm, HOST_NAME_MAX)) | ||||||
|  |     return hm; | ||||||
|  |   else { | ||||||
|  |     if(hm) free(hm); | ||||||
|  |     return NULL; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline int __removechar(char *b, size_t chrs) | ||||||
|  | { | ||||||
|  |   char *c = b + chrs; | ||||||
|  |   size_t blen = strlen(c) + sizeof(char); | ||||||
|  | 
 | ||||||
|  |   memcpy(b, c, blen); | ||||||
|  | 
 | ||||||
|  |   return chrs; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int normalize_path(char *path) | ||||||
|  | { | ||||||
|  |   char *obuf = path; | ||||||
|  |   int cutlen; | ||||||
|  | 
 | ||||||
|  |   /* first remove useless / if found */ | ||||||
|  |   while((obuf = strchr(obuf, '/'))) { | ||||||
|  |     obuf++; | ||||||
|  |     while(*obuf == '/') __removechar(obuf, 1); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   obuf = path; /* much cleaner now */ | ||||||
|  |   while(*obuf != '\0') { | ||||||
|  |     if(*obuf == '.' && *(obuf - 1) == '/') { | ||||||
|  |       if(!strcmp(obuf, "./")) __removechar(obuf, 2); | ||||||
|  |       else if(!strcmp(obuf, "../")) { | ||||||
|  |         cutlen = strlen(path) - strlen(obuf); | ||||||
|  |         if(cutlen < 4) return -1; | ||||||
|  |         else cutlen = 4; | ||||||
|  |         obuf -= 2; | ||||||
|  |         while(*obuf != '/') { | ||||||
|  |           obuf--; cutlen++; | ||||||
|  |         } | ||||||
|  |         __removechar(obuf, cutlen); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     obuf++; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return 0; | ||||||
|  | } | ||||||
|  | |||||||
| @ -24,4 +24,8 @@ | |||||||
| 
 | 
 | ||||||
| int openlistener_socket(int port); | int openlistener_socket(int port); | ||||||
| 
 | 
 | ||||||
|  | char *nodehostname(void); | ||||||
|  | 
 | ||||||
|  | int normalize_path(char *path); | ||||||
|  | 
 | ||||||
| #endif /* __SXMP_EXAMPLES_HELPERS_H__ */ | #endif /* __SXMP_EXAMPLES_HELPERS_H__ */ | ||||||
|  | |||||||
							
								
								
									
										270
									
								
								examples/smpfd.c
									
									
									
									
									
								
							
							
						
						
									
										270
									
								
								examples/smpfd.c
									
									
									
									
									
								
							| @ -76,10 +76,6 @@ static usrtc_t *fulist; | |||||||
| /* ok, here we will define out sxmp specific functions */ | /* ok, here we will define out sxmp specific functions */ | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * RPC list contain groups of RPC calls called channel types |  | ||||||
|  * for each sxmp link depends on access rules you can change |  | ||||||
|  * available channel types. |  | ||||||
|  * To do so you must provide a special callback returning this list. |  | ||||||
|  * Since we haven't any access restrictions in our example, just |  * Since we haven't any access restrictions in our example, just | ||||||
|  * create a fake. |  * create a fake. | ||||||
|  */ |  */ | ||||||
| @ -89,11 +85,6 @@ static usrtc_t *__rettlist(sxlink_t *l) | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Each sxmp link validated by certificate ID, |  | ||||||
|  * i.e. when basic checking is done, you can also |  | ||||||
|  * review the certificate ID, for example you need |  | ||||||
|  * to disable certificate for a time being. |  | ||||||
|  * |  | ||||||
|  * Here we don't have those checks, just always accept |  * Here we don't have those checks, just always accept | ||||||
|  */ |  */ | ||||||
| static int __validate_sslpem(sxlink_t *l) | static int __validate_sslpem(sxlink_t *l) | ||||||
| @ -102,16 +93,32 @@ static int __validate_sslpem(sxlink_t *l) | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * To be more paranoic, sxmp also allow to |  * don't check password and login, | ||||||
|  * check up username and password. |  * but assign session info for each link. | ||||||
|  * We don't overview this tuff here, just |  | ||||||
|  * always allow. |  | ||||||
|  */ |  */ | ||||||
| static int __secure_check(sxlink_t *l) | static int __secure_check(sxlink_t *l) | ||||||
| { | { | ||||||
|  |   struct mp_session *session; | ||||||
|  | 
 | ||||||
|  |   if(!(session = malloc(sizeof(struct mp_session)))) | ||||||
|  |     return SXE_ENOMEM; | ||||||
|  | 
 | ||||||
|  |   session->link = l; | ||||||
|  |   strcpy(session->cwd, daemon_ctx.root_dir); | ||||||
|  |   sxlink_setpriv(l, session); | ||||||
|  | 
 | ||||||
|   return SXE_SUCCESS; |   return SXE_SUCCESS; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void __session_free(sxlink_t *l) | ||||||
|  | { | ||||||
|  |   struct mp_session *session = (struct mp_session *)sxlink_getpriv(l); | ||||||
|  | 
 | ||||||
|  |   if(session) free(session); | ||||||
|  | 
 | ||||||
|  |   return; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /* remote functions implementation */ | /* remote functions implementation */ | ||||||
| /* misc functions */ | /* misc functions */ | ||||||
| static int __ping(void *m, sexp_t *sx) | static int __ping(void *m, sexp_t *sx) | ||||||
| @ -155,6 +162,188 @@ static void __version_print(FILE *fso) | |||||||
|   return; |   return; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /* control operations */ | ||||||
|  | static int __setcwd(void *m, sexp_t *sx) | ||||||
|  | { | ||||||
|  |   sxmsg_t *msg = (sxmsg_t*)m; | ||||||
|  |   sxlink_t *link = sxmsg_link(msg); | ||||||
|  |   char *dirname = NULL, *odir = NULL; | ||||||
|  |   sexp_t *isx; | ||||||
|  |   int r = SXE_SUCCESS, idx, olen = 0; | ||||||
|  |   struct mp_session *session = (struct mp_session *)sxlink_getpriv(link); | ||||||
|  | 
 | ||||||
|  |   SEXP_ITERATE_LIST(sx, isx, idx) { | ||||||
|  |     if(isx->ty == SEXP_LIST) r = SXE_BADPROTO; | ||||||
|  |     if(idx > 1) r = SXE_BADPROTO; | ||||||
|  | 
 | ||||||
|  |     if(idx) dirname = isx->val; | ||||||
|  |   } | ||||||
|  |   if(r != SXE_SUCCESS || !dirname) goto __fini; | ||||||
|  |   if(!strcmp(dirname, "./")) goto __fini; | ||||||
|  |   if(!strlen(dirname) || !strcmp(dirname, ".")) goto __fini; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |   if(*dirname == '/') odir = strdup(dirname); | ||||||
|  |   else { | ||||||
|  |     olen = strlen(session->cwd) + strlen(dirname) + 2*sizeof(char); | ||||||
|  |     odir = malloc(olen); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if(!odir) { | ||||||
|  |     r = SXE_ENOMEM; | ||||||
|  |     goto __fini; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if(olen) snprintf(odir, olen, "%s/%s", session->cwd, dirname); | ||||||
|  | 
 | ||||||
|  |   if(normalize_path(odir)) r = SXE_FAILED; | ||||||
|  |   else strcpy(session->cwd, odir); | ||||||
|  | 
 | ||||||
|  |  __fini: | ||||||
|  |   if(odir) free(odir); | ||||||
|  |   return sxmsg_return(msg, r); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* readonly operations */ | ||||||
|  | static int __getcwd(void *m, sexp_t *sx) | ||||||
|  | { | ||||||
|  |   sxmsg_t *msg = (sxmsg_t*)m; | ||||||
|  |   sxlink_t *link = sxmsg_link(msg); | ||||||
|  |   char *rbuf = sxmsg_rapidbuf(msg); | ||||||
|  |   size_t rbuf_len = 0; | ||||||
|  |   struct mp_session *session = (struct mp_session *)sxlink_getpriv(link); | ||||||
|  | 
 | ||||||
|  |   rbuf_len = snprintf(rbuf, MAX_RBBUF_LEN, "(\"%s\")", session->cwd); | ||||||
|  | 
 | ||||||
|  |   return sxmsg_rreply(msg, rbuf_len); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* stream, simple entry nonamed streams */ | ||||||
|  | /* dir listing stream */ | ||||||
|  | typedef struct __dirlist_type { | ||||||
|  |   DIR *dp; | ||||||
|  |   struct dirent dent; | ||||||
|  |   struct dirent *dres; | ||||||
|  | } dirlist_t; | ||||||
|  | 
 | ||||||
|  | static int dirlist_open(sxlink_t *link, struct sxstream_opened *stream, | ||||||
|  |                         const char *dirname) | ||||||
|  | { | ||||||
|  |   dirlist_t *pslist = malloc(sizeof(dirlist_t)); | ||||||
|  |   char *odir = NULL; | ||||||
|  |   struct mp_session *session = (struct mp_session *)sxlink_getpriv(link); | ||||||
|  |   int olen = 0; | ||||||
|  | 
 | ||||||
|  |   if(!pslist) return SXE_ENOMEM; | ||||||
|  |   else memset(pslist, 0, sizeof(dirlist_t)); | ||||||
|  | 
 | ||||||
|  |   if(!dirname) odir = session->cwd; | ||||||
|  |   else if(*dirname == '/') odir = (char *)dirname; | ||||||
|  |   else { | ||||||
|  |     olen = strlen(dirname) + strlen(session->cwd) + 2*sizeof(char); | ||||||
|  |     if(!(odir = malloc(olen))) { | ||||||
|  |       free(pslist); | ||||||
|  |       return SXE_ENOMEM; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     snprintf(odir, olen, "%s/%s", session->cwd, dirname); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if(!(pslist->dp = opendir(odir))) { | ||||||
|  |     if(dirname && *dirname != '/') free(odir); | ||||||
|  |     free(pslist); | ||||||
|  |     return SXE_FAILED; | ||||||
|  |   } else sxstream_opened_setpriv(stream, pslist); | ||||||
|  | 
 | ||||||
|  |   if(dirname && *dirname != '/') free(odir); | ||||||
|  | 
 | ||||||
|  |   return SXE_SUCCESS; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int dirlist_close(struct sxstream_opened *stream) | ||||||
|  | { | ||||||
|  |   dirlist_t *pslist = sxstream_opened_getpriv(stream); | ||||||
|  |   list_head_t *llist = sxstream_opened_getelist(stream); | ||||||
|  | 
 | ||||||
|  |   if(!pslist) return SXE_FAILED; | ||||||
|  |   if(llist) sxstream_generic_slist_free(llist); | ||||||
|  | 
 | ||||||
|  |   /* close dir and free strcuture */ | ||||||
|  |   if(pslist->dp) closedir(pslist->dp); | ||||||
|  |   free(pslist); | ||||||
|  | 
 | ||||||
|  |   return SXE_SUCCESS; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline const char *dump_type(struct dirent *d) | ||||||
|  | { | ||||||
|  |   if(!d) return "nil"; | ||||||
|  | 
 | ||||||
|  |   switch(d->d_type) { | ||||||
|  |   case DT_REG:    return "regular"; | ||||||
|  |   case DT_DIR:    return "directory"; | ||||||
|  |   case DT_BLK:    return "block"; | ||||||
|  |   case DT_CHR:    return "char"; | ||||||
|  |   case DT_FIFO:    return "fifo"; | ||||||
|  |   case DT_LNK:    return "link"; | ||||||
|  |   case DT_UNKNOWN:    return "unknown"; | ||||||
|  |   default:    return "another"; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return "nil"; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static size_t dirlist_read(struct sxstream_opened *stream, size_t sz, uint64_t off, | ||||||
|  |                            list_head_t **rlist) | ||||||
|  | { | ||||||
|  |   dirlist_t *pslist = sxstream_opened_getpriv(stream); | ||||||
|  |   list_head_t *llist_prev = sxstream_opened_getelist(stream); | ||||||
|  |   list_head_t *llist_new = NULL; | ||||||
|  | 
 | ||||||
|  |   if(!pslist) return -1; | ||||||
|  | 
 | ||||||
|  |   /* read and fill new list */ | ||||||
|  |   if(readdir_r(pslist->dp, &(pslist->dent), &(pslist->dres))) return -1; | ||||||
|  | 
 | ||||||
|  |   /* if finished return 0 */ | ||||||
|  |   if(!pslist->dres) { | ||||||
|  |     if(llist_prev) sxstream_generic_slist_free(llist_prev); | ||||||
|  |     stream->ent_buf = NULL; | ||||||
|  |     return 0; | ||||||
|  |   } | ||||||
|  |   /* allocate a new */ | ||||||
|  |   if(!(llist_new = sxstream_generic_slist_alloc())) return -1; | ||||||
|  |   else { /* fill this list */ | ||||||
|  |     if(sxstream_generic_slist_additem(llist_new, pslist->dres->d_name)) { | ||||||
|  |     __fail: | ||||||
|  |       sxstream_generic_slist_free(llist_new); | ||||||
|  |       return -1; | ||||||
|  |     } | ||||||
|  |     if(sxstream_generic_slist_additem(llist_new, dump_type(pslist->dres))) | ||||||
|  |       goto __fail; | ||||||
|  |   } | ||||||
|  |   /* otherwise destroy last list */ | ||||||
|  |   if(llist_prev) sxstream_generic_slist_free(llist_prev); | ||||||
|  |   *rlist = llist_new; /* assign new list */ | ||||||
|  | 
 | ||||||
|  |   return 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static struct sxstream_ops dirlist_ops = { | ||||||
|  |   .s_open = dirlist_open, | ||||||
|  |   .s_close = dirlist_close, | ||||||
|  |   .s_eread = dirlist_read, | ||||||
|  |   .s_ewrite = NULL, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static struct sxstream_description dirlist_stream = { | ||||||
|  |   .stid = DIRLIST_ID, | ||||||
|  |   .pcid = READONLY_CHANNEL, | ||||||
|  |   .type = 0, /* just a simple one */ | ||||||
|  |   .flags = SXE_O_READ | SXE_O_TRUNC, | ||||||
|  |   .ops = &dirlist_ops, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| int main(int argc, char **argv) | int main(int argc, char **argv) | ||||||
| { | { | ||||||
|   char *rootca = NULL, *cert = NULL; |   char *rootca = NULL, *cert = NULL; | ||||||
| @ -241,11 +430,17 @@ int main(int argc, char **argv) | |||||||
|   /* clean up */ |   /* clean up */ | ||||||
|   free(rootca); |   free(rootca); | ||||||
|   free(cert); |   free(cert); | ||||||
|   free(root_dir); | 
 | ||||||
|  |   /* set context */ | ||||||
|  |   daemon_ctx.root_dir = root_dir; | ||||||
|  |   daemon_ctx.root = NULL; | ||||||
|  |   daemon_ctx.hostname = nodehostname(); | ||||||
| 
 | 
 | ||||||
|   /* set important callbacks to do the security checking */ |   /* set important callbacks to do the security checking */ | ||||||
|   sxhub_set_authcheck(sxmphub, __secure_check); |   sxhub_set_authcheck(sxmphub, __secure_check); | ||||||
|   sxhub_set_sslvalidate(sxmphub, __validate_sslpem); |   sxhub_set_sslvalidate(sxmphub, __validate_sslpem); | ||||||
|  |   /* we using our internal session info */ | ||||||
|  |   sxhub_set_ondestroy(sxmphub, __session_free); | ||||||
| 
 | 
 | ||||||
|   /* ok, now we need to construct RPC lists (channels) */ |   /* ok, now we need to construct RPC lists (channels) */ | ||||||
|   if(!(fulist = malloc(sizeof(usrtc_t)))) { |   if(!(fulist = malloc(sizeof(usrtc_t)))) { | ||||||
| @ -258,26 +453,59 @@ int main(int argc, char **argv) | |||||||
|     return opt; |     return opt; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   /* we will add one channel with type id READONLY_CHANNEL for read only operations */ |   /*
 | ||||||
|   opt = sxmp_rpclist_add(fulist, READONLY_CHANNEL, "Read only operations", NULL); |    * Public channel | ||||||
|  |    */ | ||||||
|  |   opt = sxmp_rpclist_add(fulist, PUBLIC_CHANNEL, "Public channel", NULL); | ||||||
|   if(opt) { |   if(opt) { | ||||||
|  |   __failaddchannel: | ||||||
|     fprintf(stderr, "Failed to add typed RPC channel\n Failure.\n"); |     fprintf(stderr, "Failed to add typed RPC channel\n Failure.\n"); | ||||||
|     return opt; |     return opt; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   /* ok, let's add stream functions */ |   opt = sxmp_rpclist_add_function(fulist, PUBLIC_CHANNEL, PING_CMD, __ping); | ||||||
|   opt = sxmp_rpclist_add_function(fulist, READONLY_CHANNEL, "ping", __ping); |  | ||||||
|   if(opt) { |   if(opt) { | ||||||
|  |   __failaddrpc: | ||||||
|     fprintf(stderr, "Failed to add functions to typed RPC channel\n Failure.\n"); |     fprintf(stderr, "Failed to add functions to typed RPC channel\n Failure.\n"); | ||||||
|     return opt; |     return opt; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   /*
 | ||||||
|  |    * Readonly channel | ||||||
|  |    */ | ||||||
|  |   opt = sxmp_rpclist_add(fulist, READONLY_CHANNEL, "Read only operations", NULL); | ||||||
|  |   if(opt) goto __failaddchannel; | ||||||
|  | 
 | ||||||
|  |   /* ok, let's add read functions */ | ||||||
|  |   opt = sxmp_rpclist_add_function(fulist, READONLY_CHANNEL, CWD_CMD, __setcwd); | ||||||
|  |   if(opt) goto __failaddrpc; | ||||||
|  |   opt = sxmp_rpclist_add_function(fulist, READONLY_CHANNEL, GETCWD_CMD, __getcwd); | ||||||
|  |   if(opt) goto __failaddrpc; | ||||||
|  |   opt = sxmp_rpclist_add_function(fulist, READONLY_CHANNEL, STAT_CMD, __ping); | ||||||
|  |   if(opt) goto __failaddrpc; | ||||||
|  | 
 | ||||||
|  |   /* streams */ | ||||||
|  |   sxhub_stream_register(sxmphub, &dirlist_stream); | ||||||
|  | 
 | ||||||
|  |   /*
 | ||||||
|  |    * Write channel | ||||||
|  |    */ | ||||||
|  |   opt = sxmp_rpclist_add(fulist, WRITEONLY_CHANNEL, "Write only operations", NULL); | ||||||
|  |   if(opt) goto __failaddchannel; | ||||||
|  | 
 | ||||||
|  |   /* functions */ | ||||||
|  |   opt = sxmp_rpclist_add_function(fulist, WRITEONLY_CHANNEL, CREAT_CMD, __ping); | ||||||
|  |   if(opt) goto __failaddrpc; | ||||||
|  |   opt = sxmp_rpclist_add_function(fulist, WRITEONLY_CHANNEL, MKDIR_CMD, __ping); | ||||||
|  |   if(opt) goto __failaddrpc; | ||||||
|  |   opt = sxmp_rpclist_add_function(fulist, WRITEONLY_CHANNEL, RMDIR_CMD, __ping); | ||||||
|  |   if(opt) goto __failaddrpc; | ||||||
|  |   opt = sxmp_rpclist_add_function(fulist, WRITEONLY_CHANNEL, UNLINK_CMD, __ping); | ||||||
|  |   if(opt) goto __failaddrpc; | ||||||
|  | 
 | ||||||
|   /* ok, setup it */ |   /* ok, setup it */ | ||||||
|   sxhub_set_rpcvalidator(sxmphub, __rettlist); |   sxhub_set_rpcvalidator(sxmphub, __rettlist); | ||||||
| 
 | 
 | ||||||
|   /* setup our stream */ |  | ||||||
|   //  sxhub_stream_register(sxmphub, &dirlist_stream);
 |  | ||||||
| 
 |  | ||||||
|   signal(SIGPIPE, SIG_IGN); |   signal(SIGPIPE, SIG_IGN); | ||||||
| 
 | 
 | ||||||
|   /* now we're ready to run the listen process */ |   /* now we're ready to run the listen process */ | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user