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 }