packetfs.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487
  1. /* vim: tabstop=4 shiftwidth=4 noexpandtab
  2. * This file is part of ToaruOS and is released under the terms
  3. * of the NCSA / University of Illinois License - see LICENSE.md
  4. * Copyright (C) 2014-2018 K. Lange
  5. */
  6. #include <kernel/system.h>
  7. #include <kernel/fs.h>
  8. #include <kernel/pipe.h>
  9. #include <kernel/module.h>
  10. #include <kernel/logging.h>
  11. #include <sys/ioctl.h>
  12. #define MAX_PACKET_SIZE 1024
  13. typedef struct packet_manager {
  14. /* uh, nothing, lol */
  15. list_t * exchanges;
  16. spin_lock_t lock;
  17. } pex_t;
  18. typedef struct packet_exchange {
  19. char * name;
  20. char fresh;
  21. spin_lock_t lock;
  22. fs_node_t * server_pipe;
  23. list_t * clients;
  24. } pex_ex_t;
  25. typedef struct packet_client {
  26. pex_ex_t * parent;
  27. fs_node_t * pipe;
  28. } pex_client_t;
  29. typedef struct packet {
  30. pex_client_t * source;
  31. size_t size;
  32. uint8_t data[];
  33. } packet_t;
  34. typedef struct server_write_header {
  35. pex_client_t * target;
  36. uint8_t data[];
  37. } header_t;
  38. static void receive_packet(fs_node_t * socket, packet_t ** out) {
  39. packet_t tmp;
  40. read_fs(socket, 0, sizeof(struct packet), (uint8_t *)&tmp);
  41. *out = malloc(tmp.size + sizeof(struct packet));
  42. memcpy(*out, &tmp, sizeof(struct packet));
  43. if (tmp.size) {
  44. read_fs(socket, 0, tmp.size, (uint8_t *)(*out)->data);
  45. }
  46. }
  47. static void send_to_server(pex_ex_t * p, pex_client_t * c, size_t size, void * data) {
  48. size_t p_size = size + sizeof(struct packet);
  49. packet_t * packet = malloc(p_size);
  50. packet->source = c;
  51. packet->size = size;
  52. if (size) {
  53. memcpy(packet->data, data, size);
  54. }
  55. write_fs(p->server_pipe, 0, p_size, (uint8_t *)packet);
  56. free(packet);
  57. }
  58. static int send_to_client(pex_ex_t * p, pex_client_t * c, size_t size, void * data) {
  59. size_t p_size = size + sizeof(struct packet);
  60. /* Verify there is space on the client */
  61. if (pipe_unsize(c->pipe) < (int)p_size) {
  62. return -1;
  63. }
  64. packet_t * packet = malloc(p_size);
  65. memcpy(packet->data, data, size);
  66. packet->source = NULL;
  67. packet->size = size;
  68. write_fs(c->pipe, 0, p_size, (uint8_t *)packet);
  69. free(packet);
  70. return size;
  71. }
  72. static pex_client_t * create_client(pex_ex_t * p) {
  73. pex_client_t * out = malloc(sizeof(pex_client_t));
  74. out->parent = p;
  75. out->pipe = make_pipe(4096);
  76. return out;
  77. }
  78. static uint32_t read_server(fs_node_t * node, uint32_t offset, uint32_t size, uint8_t * buffer) {
  79. pex_ex_t * p = (pex_ex_t *)node->device;
  80. debug_print(INFO, "[pex] server read(...)");
  81. packet_t * packet;
  82. receive_packet(p->server_pipe, &packet);
  83. debug_print(INFO, "Server recevied packet of size %d, was waiting for at most %d", packet->size, size);
  84. if (packet->size + sizeof(packet_t) > size) {
  85. return -1;
  86. }
  87. memcpy(buffer, packet, packet->size + sizeof(packet_t));
  88. uint32_t out = packet->size + sizeof(packet_t);
  89. free(packet);
  90. return out;
  91. }
  92. static uint32_t write_server(fs_node_t * node, uint32_t offset, uint32_t size, uint8_t * buffer) {
  93. pex_ex_t * p = (pex_ex_t *)node->device;
  94. debug_print(INFO, "[pex] server write(...)");
  95. header_t * head = (header_t *)buffer;
  96. if (size - sizeof(header_t) > MAX_PACKET_SIZE) {
  97. return -1;
  98. }
  99. if (head->target == NULL) {
  100. /* Brodcast packet */
  101. spin_lock(p->lock);
  102. foreach(f, p->clients) {
  103. debug_print(INFO, "Sending to client 0x%x", f->value);
  104. send_to_client(p, (pex_client_t *)f->value, size - sizeof(header_t), head->data);
  105. }
  106. spin_unlock(p->lock);
  107. debug_print(INFO, "Done broadcasting to clients.");
  108. return size;
  109. } else if (head->target->parent != p) {
  110. debug_print(WARNING, "[pex] Invalid packet from server? (pid=%d)", current_process->id);
  111. return -1;
  112. }
  113. return send_to_client(p, head->target, size - sizeof(header_t), head->data);
  114. }
  115. static int ioctl_server(fs_node_t * node, int request, void * argp) {
  116. pex_ex_t * p = (pex_ex_t *)node->device;
  117. switch (request) {
  118. case IOCTL_PACKETFS_QUEUED:
  119. return pipe_size(p->server_pipe);
  120. default:
  121. return -1;
  122. }
  123. }
  124. static uint32_t read_client(fs_node_t * node, uint32_t offset, uint32_t size, uint8_t * buffer) {
  125. pex_client_t * c = (pex_client_t *)node->inode;
  126. if (c->parent != node->device) {
  127. debug_print(WARNING, "[pex] Invalid device endpoint on client read?");
  128. return -1;
  129. }
  130. debug_print(INFO, "[pex] client read(...)");
  131. packet_t * packet;
  132. receive_packet(c->pipe, &packet);
  133. if (packet->size > size) {
  134. debug_print(WARNING, "[pex] Client is not reading enough bytes to hold packet of size %d", packet->size);
  135. return -1;
  136. }
  137. memcpy(buffer, &packet->data, packet->size);
  138. uint32_t out = packet->size;
  139. debug_print(INFO, "[pex] Client received packet of size %d", packet->size);
  140. free(packet);
  141. return out;
  142. }
  143. static uint32_t write_client(fs_node_t * node, uint32_t offset, uint32_t size, uint8_t * buffer) {
  144. pex_client_t * c = (pex_client_t *)node->inode;
  145. if (c->parent != node->device) {
  146. debug_print(WARNING, "[pex] Invalid device endpoint on client write?");
  147. return -1;
  148. }
  149. debug_print(INFO, "[pex] client write(...)");
  150. if (size > MAX_PACKET_SIZE) {
  151. debug_print(WARNING, "Size of %d is too big.", size);
  152. return -1;
  153. }
  154. debug_print(INFO, "Sending packet of size %d to parent", size);
  155. send_to_server(c->parent, c, size, buffer);
  156. return size;
  157. }
  158. static int ioctl_client(fs_node_t * node, int request, void * argp) {
  159. pex_client_t * c = (pex_client_t *)node->inode;
  160. switch (request) {
  161. case IOCTL_PACKETFS_QUEUED:
  162. return pipe_size(c->pipe);
  163. default:
  164. return -1;
  165. }
  166. }
  167. static void close_client(fs_node_t * node) {
  168. pex_client_t * c = (pex_client_t *)node->inode;
  169. pex_ex_t * p = c->parent;
  170. debug_print(WARNING, "Closing packetfs client: 0x%x:0x%x", p, c);
  171. spin_lock(p->lock);
  172. node_t * n = list_find(p->clients, c);
  173. if (n && n->owner == p->clients) {
  174. list_delete(p->clients, n);
  175. free(n);
  176. }
  177. spin_unlock(p->lock);
  178. char tmp[1];
  179. send_to_server(p, c, 0, tmp);
  180. free(c);
  181. }
  182. static int wait_server(fs_node_t * node, void * process) {
  183. pex_ex_t * p = (pex_ex_t *)node->device;
  184. return selectwait_fs(p->server_pipe, process);
  185. }
  186. static int check_server(fs_node_t * node) {
  187. pex_ex_t * p = (pex_ex_t *)node->device;
  188. return selectcheck_fs(p->server_pipe);
  189. }
  190. static int wait_client(fs_node_t * node, void * process) {
  191. pex_client_t * c = (pex_client_t *)node->inode;
  192. return selectwait_fs(c->pipe, process);
  193. }
  194. static int check_client(fs_node_t * node) {
  195. pex_client_t * c = (pex_client_t *)node->inode;
  196. return selectcheck_fs(c->pipe);
  197. }
  198. static void open_pex(fs_node_t * node, unsigned int flags) {
  199. pex_ex_t * t = (pex_ex_t *)(node->device);
  200. debug_print(NOTICE, "Opening packet exchange %s with flags 0x%x", t->name, flags);
  201. if (flags & O_CREAT && t->fresh) {
  202. t->fresh = 0;
  203. node->inode = 0;
  204. /* Set up the server side */
  205. node->read = read_server;
  206. node->write = write_server;
  207. node->ioctl = ioctl_server;
  208. node->selectcheck = check_server;
  209. node->selectwait = wait_server;
  210. debug_print(INFO, "[pex] Server launched: %s", t->name);
  211. debug_print(INFO, "fs_node = 0x%x", node);
  212. } else if (!(flags & O_CREAT)) {
  213. pex_client_t * client = create_client(t);
  214. node->inode = (uintptr_t)client;
  215. node->read = read_client;
  216. node->write = write_client;
  217. node->ioctl = ioctl_client;
  218. node->close = close_client;
  219. node->selectcheck = check_client;
  220. node->selectwait = wait_client;
  221. list_insert(t->clients, client);
  222. /* XXX: Send plumbing message to server for new client connection */
  223. debug_print(INFO, "[pex] Client connected: %s:0%x", t->name, node->inode);
  224. } else if (flags & O_CREAT && !t->fresh) {
  225. /* XXX: You dun goofed */
  226. }
  227. return;
  228. }
  229. static struct dirent * readdir_packetfs(fs_node_t *node, uint32_t index) {
  230. pex_t * p = (pex_t *)node->device;
  231. unsigned int i = 0;
  232. debug_print(INFO, "[pex] readdir(%d)", index);
  233. if (index == 0) {
  234. struct dirent * out = malloc(sizeof(struct dirent));
  235. memset(out, 0x00, sizeof(struct dirent));
  236. out->ino = 0;
  237. strcpy(out->name, ".");
  238. return out;
  239. }
  240. if (index == 1) {
  241. struct dirent * out = malloc(sizeof(struct dirent));
  242. memset(out, 0x00, sizeof(struct dirent));
  243. out->ino = 0;
  244. strcpy(out->name, "..");
  245. return out;
  246. }
  247. index -= 2;
  248. if (index >= p->exchanges->length) {
  249. return NULL;
  250. }
  251. spin_lock(p->lock);
  252. foreach(f, p->exchanges) {
  253. if (i == index) {
  254. spin_unlock(p->lock);
  255. pex_ex_t * t = (pex_ex_t *)f->value;
  256. struct dirent * out = malloc(sizeof(struct dirent));
  257. memset(out, 0x00, sizeof(struct dirent));
  258. out->ino = (uint32_t)t;
  259. strcpy(out->name, t->name);
  260. return out;
  261. } else {
  262. ++i;
  263. }
  264. }
  265. spin_unlock(p->lock);
  266. return NULL;
  267. }
  268. static fs_node_t * file_from_pex(pex_ex_t * pex) {
  269. fs_node_t * fnode = malloc(sizeof(fs_node_t));
  270. memset(fnode, 0x00, sizeof(fs_node_t));
  271. fnode->inode = 0;
  272. strcpy(fnode->name, pex->name);
  273. fnode->device = pex;
  274. fnode->mask = 0666;
  275. fnode->flags = FS_CHARDEVICE;
  276. fnode->open = open_pex;
  277. fnode->read = read_server;
  278. fnode->write = write_server;
  279. return fnode;
  280. }
  281. static fs_node_t * finddir_packetfs(fs_node_t * node, char * name) {
  282. if (!name) return NULL;
  283. pex_t * p = (pex_t *)node->device;
  284. debug_print(INFO, "[pex] finddir(%s)", name);
  285. spin_lock(p->lock);
  286. foreach(f, p->exchanges) {
  287. pex_ex_t * t = (pex_ex_t *)f->value;
  288. if (!strcmp(name, t->name)) {
  289. spin_unlock(p->lock);
  290. return file_from_pex(t);
  291. }
  292. }
  293. spin_unlock(p->lock);
  294. return NULL;
  295. }
  296. static int create_packetfs(fs_node_t *parent, char *name, uint16_t permission) {
  297. if (!name) return -EINVAL;
  298. pex_t * p = (pex_t *)parent->device;
  299. debug_print(NOTICE, "[pex] create(%s)", name);
  300. spin_lock(p->lock);
  301. foreach(f, p->exchanges) {
  302. pex_ex_t * t = (pex_ex_t *)f->value;
  303. if (!strcmp(name, t->name)) {
  304. spin_unlock(p->lock);
  305. /* Already exists */
  306. return -EEXIST;
  307. }
  308. }
  309. /* Make it */
  310. pex_ex_t * new_exchange = malloc(sizeof(pex_ex_t));
  311. new_exchange->name = strdup(name);
  312. new_exchange->fresh = 1;
  313. new_exchange->clients = list_create();
  314. new_exchange->server_pipe = make_pipe(4096);
  315. spin_init(new_exchange->lock);
  316. /* XXX Create exchange server pipe */
  317. list_insert(p->exchanges, new_exchange);
  318. spin_unlock(p->lock);
  319. return 0;
  320. }
  321. static void destroy_pex(pex_ex_t * p) {
  322. /* XXX */
  323. }
  324. static int unlink_packetfs(fs_node_t *parent, char *name) {
  325. if (!name) return -EINVAL;
  326. pex_t * p = (pex_t *)parent->device;
  327. debug_print(NOTICE, "[pex] unlink(%s)", name);
  328. int i = -1, j = 0;
  329. spin_lock(p->lock);
  330. foreach(f, p->exchanges) {
  331. pex_ex_t * t = (pex_ex_t *)f->value;
  332. if (!strcmp(name, t->name)) {
  333. destroy_pex(t);
  334. i = j;
  335. break;
  336. }
  337. j++;
  338. }
  339. if (i >= 0) {
  340. list_remove(p->exchanges, i);
  341. } else {
  342. spin_unlock(p->lock);
  343. return -ENOENT;
  344. }
  345. spin_unlock(p->lock);
  346. return 0;
  347. }
  348. static fs_node_t * packetfs_manager(void) {
  349. pex_t * pex = malloc(sizeof(pex_t));
  350. pex->exchanges = list_create();
  351. spin_init(pex->lock);
  352. fs_node_t * fnode = malloc(sizeof(fs_node_t));
  353. memset(fnode, 0x00, sizeof(fs_node_t));
  354. fnode->inode = 0;
  355. strcpy(fnode->name, "pex");
  356. fnode->device = pex;
  357. fnode->mask = 0777;
  358. fnode->flags = FS_DIRECTORY;
  359. fnode->readdir = readdir_packetfs;
  360. fnode->finddir = finddir_packetfs;
  361. fnode->create = create_packetfs;
  362. fnode->unlink = unlink_packetfs;
  363. return fnode;
  364. }
  365. static int init(void) {
  366. fs_node_t * packet_mgr = packetfs_manager();
  367. vfs_mount("/dev/pex", packet_mgr);
  368. return 0;
  369. }
  370. static int fini(void) {
  371. return 0;
  372. }
  373. MODULE_DEF(packetfs, init, fini);