Mercurial > hg > index.cgi
comparison src/lwwire.c @ 10:36c4cda4b6c4
Add extension support with the PINGPONG extension
Add extension support. There are two ways to add extensions:
1. as a shared object which will be loaded with ext=<filename> as a
parameter to lwwire. See the lwwire_pingpong.c file for details.
2. By doing basically the same thing as a shared object but linking it into
the main binary and calling lwwire_register_extension() appropriately.
author | William Astle <lost@l-w.ca> |
---|---|
date | Sat, 30 Jul 2016 13:16:39 -0600 |
parents | a11b330771e0 |
children | 38184ef1296d |
comparison
equal
deleted
inserted
replaced
9:a11b330771e0 | 10:36c4cda4b6c4 |
---|---|
37 */ | 37 */ |
38 | 38 |
39 // for nanosleep | 39 // for nanosleep |
40 #define _POSIX_C_SOURCE 199309L | 40 #define _POSIX_C_SOURCE 199309L |
41 | 41 |
42 #include <dlfcn.h> | |
42 #include <errno.h> | 43 #include <errno.h> |
43 #include <fcntl.h> | 44 #include <fcntl.h> |
44 #include <stdio.h> | 45 #include <stdio.h> |
45 #include <stdlib.h> | 46 #include <stdlib.h> |
46 #include <string.h> | 47 #include <string.h> |
58 { | 59 { |
59 char *path; | 60 char *path; |
60 FILE *fp; | 61 FILE *fp; |
61 int isconst; | 62 int isconst; |
62 }; | 63 }; |
64 | |
65 struct lwwire_extension_data | |
66 { | |
67 int enabled; | |
68 int (*handler)(int op); // handle op, return -1 if not supported | |
69 int (*disable)(void); // disable extension negotiated | |
70 int (*enable)(void); // enable extension negotiated (return -1 if failed to init) | |
71 void (*reset)(void); // on server reset opcode; extension will be disabled automatically here | |
72 }; | |
73 | |
74 struct lwwire_extension_data lwwire_extension_list[256]; | |
63 | 75 |
64 struct lwwire_driveinfo drivedata[256]; | 76 struct lwwire_driveinfo drivedata[256]; |
65 | 77 |
66 void lwwire_protoerror(void); | 78 void lwwire_protoerror(void); |
67 int lwwire_readdata(void *, int, int); | 79 int lwwire_readdata(void *, int, int); |
72 void lwwire_reset(void); | 84 void lwwire_reset(void); |
73 int lwwire_fetch_sector(int dn, int lsn, void *); | 85 int lwwire_fetch_sector(int dn, int lsn, void *); |
74 int lwwire_save_sector(int dn, int lsn, void *); | 86 int lwwire_save_sector(int dn, int lsn, void *); |
75 int nonblock(int); | 87 int nonblock(int); |
76 int lwwire_drive_readononly(int dn); | 88 int lwwire_drive_readononly(int dn); |
77 | 89 int lwwire_register_extension(int, int (*handler)(int), int (*enable)(void), int (*disable)(void), void (*reset)(void)); |
78 void lwwire_proto_read(void); | 90 void lwwire_proto_read(void); |
79 void lwwire_proto_write(void); | 91 void lwwire_proto_write(void); |
80 void lwwire_proto_readex(void); | 92 void lwwire_proto_readex(void); |
81 void lwwire_proto_requestextension(void); | 93 void lwwire_proto_requestextension(void); |
82 void lwwire_proto_disableextension(void); | 94 void lwwire_proto_disableextension(void); |
101 fprintf(stderr, "Cannot make stdout non-blocking: %s\n", strerror(errno)); | 113 fprintf(stderr, "Cannot make stdout non-blocking: %s\n", strerror(errno)); |
102 exit(1); | 114 exit(1); |
103 } | 115 } |
104 | 116 |
105 memset(&drivedata, 0, sizeof(drivedata)); | 117 memset(&drivedata, 0, sizeof(drivedata)); |
106 | 118 memset(lwwire_extension_list, 0, sizeof(struct lwwire_extension_data) * 256); |
119 | |
120 // call lwwire_register_extension() for each extension you define | |
121 // statically. Add those calls here, or calls to the equivalent | |
122 // of the "lwwire_register" function from a DSO type extension. | |
123 | |
107 for (i = 1; i < argc; i++) | 124 for (i = 1; i < argc; i++) |
108 { | 125 { |
109 if (strncmp("drive=", argv[i], 6) == 0) | 126 if (strncmp("ext=", argv[i], 4) == 0) |
127 { | |
128 // SO name is at argv[i]+4 | |
129 void *dlhandle; | |
130 void *initfn; | |
131 int (*rinitfn)(void); | |
132 | |
133 dlhandle = dlopen(argv[i] + 4, RTLD_NOW | RTLD_LOCAL); | |
134 if (!dlhandle) | |
135 { | |
136 fprintf(stderr, "Cannot load extension %s: %s\n", argv[i] + 4, dlerror()); | |
137 continue; | |
138 } | |
139 initfn = dlsym(dlhandle, "lwwire_register"); | |
140 if (!initfn) | |
141 { | |
142 dlclose(dlhandle); | |
143 fprintf(stderr, "Extension '%s' is not valid.\n", argv[i] + 4); | |
144 continue; | |
145 } | |
146 rinitfn = initfn; | |
147 if ((*rinitfn)() != 0) | |
148 { | |
149 dlclose(dlhandle); | |
150 fprintf(stderr, "Initialization of extension '%s' failed.\n", argv[i] + 4); | |
151 continue; | |
152 } | |
153 } | |
154 else if (strncmp("drive=", argv[i], 6) == 0) | |
110 { | 155 { |
111 int dn=0; | 156 int dn=0; |
112 int isconst = 0; | 157 int isconst = 0; |
113 char *ptr; | 158 char *ptr; |
114 ptr = argv[i] + 6; | 159 ptr = argv[i] + 6; |
329 } | 374 } |
330 | 375 |
331 void lwwire_proto_requestextension(void) | 376 void lwwire_proto_requestextension(void) |
332 { | 377 { |
333 unsigned char buf[1]; | 378 unsigned char buf[1]; |
334 | 379 int ext; |
380 | |
335 if (lwwire_read(buf, 1) < 0) | 381 if (lwwire_read(buf, 1) < 0) |
336 return; | 382 return; |
337 // NAK the request | 383 ext = buf[0]; |
338 buf[0] = 0x55; | 384 buf[0] = 0x55; // default to NAK |
385 if (lwwire_extension_list[ext].enable) | |
386 { | |
387 if ((*(lwwire_extension_list[ext].enable))() == 0) | |
388 { | |
389 // enable succeeded; enable it | |
390 buf[0] = 0x42; | |
391 lwwire_extension_list[ext].enabled = 1; | |
392 } | |
393 } | |
339 lwwire_write(buf, 1); | 394 lwwire_write(buf, 1); |
340 } | 395 } |
341 | 396 |
342 void lwwire_proto_disableextension(void) | 397 void lwwire_proto_disableextension(void) |
343 { | 398 { |
344 unsigned char buf[1]; | 399 unsigned char buf[1]; |
400 int ext; | |
345 | 401 |
346 if (lwwire_read(buf, 1) < 0) | 402 if (lwwire_read(buf, 1) < 0) |
347 return; | 403 return; |
348 // ACK disabling any unsupported extensions | 404 ext = buf[0]; |
349 buf[0] = 0x42; | 405 |
406 buf[0] = 0x42; // default to ACK | |
407 if (lwwire_extension_list[ext].disable) | |
408 { | |
409 if ((*(lwwire_extension_list[ext].disable))() != 0) | |
410 { | |
411 // extension says it can't be disabled; NAK response | |
412 buf[0] = 0x55; | |
413 } | |
414 } | |
415 if (buf[0] == 0x42) | |
416 lwwire_extension_list[ext].enabled = 0; | |
350 lwwire_write(buf, 1); | 417 lwwire_write(buf, 1); |
351 } | 418 } |
352 | 419 |
353 void lwwire_proto_extensionop(void) | 420 void lwwire_proto_extensionop(void) |
354 { | 421 { |
355 unsigned char buf[1]; | 422 unsigned char buf[2]; |
356 if (lwwire_read(buf, 1) < 0) | 423 int ext; |
357 return; | 424 int op; |
358 // we don't currently support any extensions so treat as unknown | 425 |
426 if (lwwire_read(buf, 2) < 0) | |
427 return; | |
428 ext = buf[0]; | |
429 op = buf[1]; | |
430 if (lwwire_extension_list[ext].enabled == 1) | |
431 { | |
432 if (lwwire_extension_list[ext].handler) | |
433 { | |
434 if ((*(lwwire_extension_list[ext].handler))(op) == 0) | |
435 return; | |
436 } | |
437 lwwire_protoerror(); | |
438 return; | |
439 } | |
440 // extension not enabled; do a protocol error | |
359 lwwire_protoerror(); | 441 lwwire_protoerror(); |
360 } | 442 } |
361 | 443 |
362 // Various infrastructure things follow here. | 444 // Various infrastructure things follow here. |
363 int nonblock(int fd) | 445 int nonblock(int fd) |
673 /* | 755 /* |
674 Reset the protocol state to "base protocol" mode. | 756 Reset the protocol state to "base protocol" mode. |
675 */ | 757 */ |
676 void lwwire_reset(void) | 758 void lwwire_reset(void) |
677 { | 759 { |
678 } | 760 int i; |
761 | |
762 // tell all extensions to reset and disable them | |
763 for (i = 0; i < 256; i++) | |
764 { | |
765 if (lwwire_extension_list[i].handler) | |
766 { | |
767 (*(lwwire_extension_list[i].reset))(); | |
768 } | |
769 lwwire_extension_list[i].enabled = 0; | |
770 } | |
771 } | |
772 | |
773 /* | |
774 Register an extension. This will replace the registration if the same | |
775 extension number is registered twice. Returns -1 on parameter error. | |
776 ALL function arguments are required. num must be between 0 and 255 inclusive | |
777 currently. Returns 0 if the extension is registered. | |
778 */ | |
779 int lwwire_register_extension(int num, int (*handler)(int), int (*enable)(void), int (*disable)(void), void (*reset)(void)) | |
780 { | |
781 if (!handler || !enable || !disable || !reset) | |
782 return -1; | |
783 if (num < 0 || num > 255) | |
784 return -1; | |
785 lwwire_extension_list[num].handler = handler; | |
786 lwwire_extension_list[num].enable = enable; | |
787 lwwire_extension_list[num].disable = disable; | |
788 lwwire_extension_list[num].reset = reset; | |
789 return 0; | |
790 } |