/*
FUSE Socket File System
*/

#include <fuse.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <fcntl.h>

#define NUM_SOCKS 10

struct sockinfo_s {
  int sock;
  char* host;
  unsigned int port;
};

typedef struct sockinfo_s sockinfo;

void init_sockarr(sockinfo * si);

sockinfo tcsockarr[NUM_SOCKS];
sockinfo tssockarr[NUM_SOCKS];
sockinfo ucsockarr[NUM_SOCKS];
sockinfo ussockarr[NUM_SOCKS];

static int sfs_getattr(const char * path, struct stat * stbuf) {
  memset(stbuf, 0, sizeof(struct stat));
  if(path[strlen(path) - 1] == '/' || strcmp(path, "/tcp") == 0 || strcmp(path, "/udp") == 0 || strcmp(path, "/tcp/client") == 0 || strcmp(path, "/tcp/server") == 0 || strcmp(path, "/udp/server") == 0 || strcmp(path, "/udp/client") == 0) {
    stbuf->st_mode = S_IFDIR | 0755;
    stbuf->st_nlink = 2;
  } else {
    stbuf->st_mode = S_IFREG | 0444;
    stbuf->st_nlink = 1;
    stbuf->st_size = 0;
    stbuf->st_mtime = time(NULL);
  }
  return 0;
}

static int sfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
                         off_t offset, struct fuse_file_info *fi) {
  filler(buf, ".", NULL, 0);
  filler(buf, "..", NULL, 0);
  if(strcmp("/", path) == 0) {
    filler(buf, "tcp", NULL, 0);
    filler(buf, "udp", NULL, 0);
  } else if(strcmp("/tcp", path) == 0) {
    filler(buf, "client", NULL, 0);
    filler(buf, "server", NULL, 0);
  } else if(strcmp("/udp", path) == 0) {
    filler(buf, "client", NULL, 0);
    filler(buf, "server", NULL, 0);
  } else if(strcmp("/tcp/client", path) == 0) {
    int i;
    for(i = 0; i < NUM_SOCKS; i++) {
      if(tcsockarr[i].sock != 0) {
	filler(buf, tcsockarr[i].host, NULL, 0);
      }
    }
  } else if(strcmp("/tcp/server", path) == 0) {
    int i;
    for(i = 0; i < NUM_SOCKS; i++) {
      if(tcsockarr[i].sock != 0) {
	filler(buf, tcsockarr[i].host, NULL, 0);
      }
    }
  } else {
    return -ENOENT;
  }
  return 0;
}

static struct fuse_operations sfs_oper = {
  .getattr = sfs_getattr,
  .readdir = sfs_readdir,
};

int main(int argc, char *argv[]) {
  init_sockarr(tcsockarr);
  init_sockarr(tssockarr);
  init_sockarr(ucsockarr);
  init_sockarr(ussockarr);  

  return fuse_main(argc, argv, &sfs_oper);
}

void init_sockarr(sockinfo* si) {
  int i;
  for(i = 0; i < NUM_SOCKS; i++) {
    si[i].sock = 0;
    si[i].port = 0;
    si[i].host = NULL;
  }
}

