[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; | ||||
| } | ||||
| 
 | ||||
| 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); | ||||
| 
 | ||||
| char *nodehostname(void); | ||||
| 
 | ||||
| int normalize_path(char *path); | ||||
| 
 | ||||
| #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 */ | ||||
| 
 | ||||
| /*
 | ||||
|  * 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 | ||||
|  * 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 | ||||
|  */ | ||||
| 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 | ||||
|  * check up username and password. | ||||
|  * We don't overview this tuff here, just | ||||
|  * always allow. | ||||
|  * don't check password and login, | ||||
|  * but assign session info for each link. | ||||
|  */ | ||||
| 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; | ||||
| } | ||||
| 
 | ||||
| void __session_free(sxlink_t *l) | ||||
| { | ||||
|   struct mp_session *session = (struct mp_session *)sxlink_getpriv(l); | ||||
| 
 | ||||
|   if(session) free(session); | ||||
| 
 | ||||
|   return; | ||||
| } | ||||
| 
 | ||||
| /* remote functions implementation */ | ||||
| /* misc functions */ | ||||
| static int __ping(void *m, sexp_t *sx) | ||||
| @ -155,6 +162,188 @@ static void __version_print(FILE *fso) | ||||
|   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) | ||||
| { | ||||
|   char *rootca = NULL, *cert = NULL; | ||||
| @ -241,11 +430,17 @@ int main(int argc, char **argv) | ||||
|   /* clean up */ | ||||
|   free(rootca); | ||||
|   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 */ | ||||
|   sxhub_set_authcheck(sxmphub, __secure_check); | ||||
|   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) */ | ||||
|   if(!(fulist = malloc(sizeof(usrtc_t)))) { | ||||
| @ -258,26 +453,59 @@ int main(int argc, char **argv) | ||||
|     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) { | ||||
|   __failaddchannel: | ||||
|     fprintf(stderr, "Failed to add typed RPC channel\n Failure.\n"); | ||||
|     return opt; | ||||
|   } | ||||
| 
 | ||||
|   /* ok, let's add stream functions */ | ||||
|   opt = sxmp_rpclist_add_function(fulist, READONLY_CHANNEL, "ping", __ping); | ||||
|   opt = sxmp_rpclist_add_function(fulist, PUBLIC_CHANNEL, PING_CMD, __ping); | ||||
|   if(opt) { | ||||
|   __failaddrpc: | ||||
|     fprintf(stderr, "Failed to add functions to typed RPC channel\n Failure.\n"); | ||||
|     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 */ | ||||
|   sxhub_set_rpcvalidator(sxmphub, __rettlist); | ||||
| 
 | ||||
|   /* setup our stream */ | ||||
|   //  sxhub_stream_register(sxmphub, &dirlist_stream);
 | ||||
| 
 | ||||
|   signal(SIGPIPE, SIG_IGN); | ||||
| 
 | ||||
|   /* now we're ready to run the listen process */ | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user