1 /* AirScan (a.k.a. eSCL) backend for SANE
2 *
3 * Copyright (C) 2019 and up by Alexander Pevzner (pzz@apevzner.com)
4 * See LICENSE for license terms and conditions
5 */
6
7 #ifndef airscan_h
8 #define airscan_h
9
10 #include <avahi-common/address.h>
11 #include <avahi-common/strlst.h>
12 #include <avahi-common/watch.h>
13
14 #include <sane/sane.h>
15 #include <sane/saneopts.h>
16
17 #include <ctype.h>
18 #include <math.h>
19 #include <pthread.h>
20 #include <stdbool.h>
21 #include <stddef.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <time.h>
25
26 #include <netinet/in.h>
27 #include <sys/param.h>
28 #include <sys/socket.h>
29 #include <sys/types.h>
30
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
34
35 /******************** Static configuration ********************/
36 /* Configuration path in environment
37 */
38 #define CONFIG_PATH_ENV "SANE_CONFIG_DIR"
39
40 /* Standard SANE configuration directory
41 */
42 #ifndef CONFIG_SANE_CONFIG_DIR
43 # define CONFIG_SANE_CONFIG_DIR "/etc/sane.d/"
44 #endif
45
46 /* Sane-airscan configuration file and subdirectory names
47 */
48 #define CONFIG_AIRSCAN_CONF "airscan.conf"
49 #define CONFIG_AIRSCAN_D "airscan.d"
50
51 /* Environment variables
52 */
53 #define CONFIG_ENV_AIRSCAN_DEBUG "SANE_DEBUG_AIRSCAN"
54
55 /* Default resolution, DPI
56 */
57 #define CONFIG_DEFAULT_RESOLUTION 300
58
59 /* Minimal interval between subsequent sane_start()
60 * attempts, if previous sane_start was failed
61 */
62 #define CONFIG_START_RETRY_INTERVAL 2500
63
64 /* Default directory for AF_UNIX sockets
65 */
66 #define CONFIG_DEFAULT_SOCKET_DIR "/var/run"
67
68 /******************** Forward declarations ********************/
69 /* log_ctx represents logging context
70 */
71 typedef struct log_ctx log_ctx;
72
73 /* Type http_uri represents HTTP URI
74 */
75 typedef struct http_uri http_uri;
76
77 /******************** Utility macros ********************/
78 /* Obtain pointer to outer structure from pointer to
79 * its known member
80 */
81 #define OUTER_STRUCT(member_p,struct_t,field) \
82 ((struct_t*)((char*)(member_p) - ((ptrdiff_t) &(((struct_t*) 0)->field))))
83
84 /******************** Circular Linked Lists ********************/
85 /* ll_node represents a linked data node.
86 * Data nodes are embedded into the corresponding data structures:
87 * struct data {
88 * ll_node chain; // Linked list chain
89 * ...
90 * };
91 *
92 * Use OUTER_STRUCT() macro to obtain pointer to containing
93 * structure from the pointer to the list node
94 */
95 typedef struct ll_node ll_node;
96 struct ll_node {
97 ll_node *ll_prev, *ll_next;
98 };
99
100 /* ll_head represents a linked list head node
101 * ll_head must be initialized before use with ll_init() function
102 */
103 typedef struct {
104 ll_node node;
105 } ll_head;
106
107 /* Initialize list head
108 */
109 static inline void
ll_init(ll_head * head)110 ll_init (ll_head *head)
111 {
112 head->node.ll_next = head->node.ll_prev = &head->node;
113 }
114
115 /* Check if list is empty
116 */
117 static inline bool
ll_empty(const ll_head * head)118 ll_empty (const ll_head *head)
119 {
120 return head->node.ll_next == &head->node;
121 }
122
123 /* Push node to the end of the list, represented
124 * by its head node
125 */
126 static inline void
ll_push_end(ll_head * head,ll_node * node)127 ll_push_end (ll_head *head, ll_node *node)
128 {
129 node->ll_prev = head->node.ll_prev;
130 node->ll_next = &head->node;
131 head->node.ll_prev->ll_next = node;
132 head->node.ll_prev = node;
133 }
134
135 /* Push node to the beginning of the list, represented
136 * by its head node
137 */
138 static inline void
ll_push_beg(ll_head * head,ll_node * node)139 ll_push_beg (ll_head *head, ll_node *node)
140 {
141 node->ll_next = head->node.ll_next;
142 node->ll_prev = &head->node;
143 head->node.ll_next->ll_prev = node;
144 head->node.ll_next = node;
145 }
146
147 /* Delete node from the list
148 */
149 static inline void
ll_del(ll_node * node)150 ll_del (ll_node *node)
151 {
152 ll_node *p = node->ll_prev, *n = node->ll_next;
153
154 p->ll_next = n;
155 n->ll_prev = p;
156
157 /* Make double-delete safe */
158 node->ll_next = node->ll_prev = node;
159 }
160
161 /* Pop node from the beginning of the list.
162 * Returns NULL if list is empty
163 */
164 static inline ll_node*
ll_pop_beg(ll_head * head)165 ll_pop_beg (ll_head *head)
166 {
167 ll_node *node, *next;
168
169 node = head->node.ll_next;
170 if (node == &head->node) {
171 return NULL; /* List is empty if it is looped to itself */
172 }
173
174 next = node->ll_next;
175 next->ll_prev = &head->node;
176 head->node.ll_next = next;
177
178 /* Make double-delete safe */
179 node->ll_next = node->ll_prev = node;
180
181 return node;
182 }
183
184 /* Pop node from the end of the list.
185 * Returns NULL if list is empty
186 */
187 static inline ll_node*
ll_pop_end(ll_head * head)188 ll_pop_end (ll_head *head)
189 {
190 ll_node *node, *prev;
191
192 node = head->node.ll_prev;
193 if (node == &head->node) {
194 return NULL; /* List is empty if it is looped to itself */
195 }
196
197 prev = node->ll_prev;
198 prev->ll_next = &head->node;
199 head->node.ll_prev = prev;
200
201 /* Make double-delete safe */
202 node->ll_next = node->ll_prev = node;
203
204 return node;
205 }
206
207 /* Get next (from the beginning to the end) node of
208 * the list. Returns NULL, if end of list is reached
209 */
210 static inline ll_node*
ll_next(const ll_head * head,const ll_node * node)211 ll_next (const ll_head *head, const ll_node *node)
212 {
213 ll_node *next = node->ll_next;
214 return next == &head->node ? NULL : next;
215 }
216
217 /* Get previous (from the beginning to the end) node of
218 * the list. Returns NULL, if end of list is reached
219 */
220 static inline ll_node*
ll_prev(const ll_head * head,const ll_node * node)221 ll_prev (const ll_head *head, const ll_node *node)
222 {
223 ll_node *prev = node->ll_prev;
224 return prev == &head->node ? NULL : prev;
225 }
226
227 /* Get first node of the list.
228 * Returns NULL if list is empty
229 */
230 static inline ll_node*
ll_first(const ll_head * head)231 ll_first (const ll_head *head)
232 {
233 return ll_next(head, &head->node);
234 }
235
236 /* Get last node of the list.
237 * Returns NULL if list is empty
238 */
239 static inline ll_node*
ll_last(const ll_head * head)240 ll_last (const ll_head *head)
241 {
242 return ll_prev(head, &head->node);
243 }
244
245 /* Concatenate lists:
246 * list1 += list2
247 * list2 = empty
248 */
249 static inline void
ll_cat(ll_head * list1,ll_head * list2)250 ll_cat (ll_head *list1, ll_head *list2)
251 {
252 if (ll_empty(list2)) {
253 return;
254 }
255
256 list2->node.ll_prev->ll_next = &list1->node;
257 list2->node.ll_next->ll_prev = list1->node.ll_prev;
258 list1->node.ll_prev->ll_next = list2->node.ll_next;
259 list1->node.ll_prev = list2->node.ll_prev;
260
261 ll_init(list2);
262 }
263
264 /* Helper macro for list iteration.
265 * Usage:
266 * for (LL_FOR_EACH(node, list)) {
267 * // do something with the node
268 * }
269 */
270 #define LL_FOR_EACH(node,list) \
271 node = ll_first(list); node != NULL; node = ll_next(list, node)
272
273 /******************** Memory allocation ********************/
274 /* Allocate `len' elements of type T
275 */
276 #define mem_new(T,len) ((T*) __mem_alloc(len, 0, sizeof(T), true))
277
278 /* Resize memory. The returned memory block has length of `len' and
279 * capacity at least of `len' + `extra'
280 *
281 * If p is NULL, new memory block will be allocated. Otherwise,
282 * existent memory block will be resized, new pointer is returned,
283 * while old becomes invalid (similar to how realloc() works).
284 *
285 * This function never returns NULL, it panics in a case of
286 * memory allocation error.
287 */
288 #define mem_resize(p,len,extra) \
289 ((__typeof__(p)) __mem_resize(p,len,extra,sizeof(*p),true))
290
291 /* Try to resize memory. It works like mem_resize() but may
292 * return NULL if memory allocation failed.
293 */
294 #define mem_try_resize(p,len,extra) __mem_resize(p,len,extra,sizeof(*p),false)
295
296 /* Truncate the memory block length, preserving its capacity
297 */
298 void
299 mem_trunc (void *p);
300
301 /* Shrink the memory block length, preserving its capacity
302 */
303 #define mem_shrink(p,len) __mem_shrink(p,len, sizeof(*p))
304
305 /* Free memory block, obtained from mem_new() or mem_resize()
306 * `p' can be NULL
307 */
308 void
309 mem_free (void *p);
310
311 /* Get memory block length/capacity, in bytes
312 * For NULL pointer return 0
313 */
314 size_t mem_len_bytes (const void *p);
315 size_t mem_cap_bytes (const void *p);
316
317 /* Get memory block length/capacity, in elements
318 * For NULL pointer return 0
319 */
320 #define mem_len(v) (mem_len_bytes(v) / sizeof(*v))
321 #define mem_cap(v) (mem_cap_bytes(v) / sizeof(*v))
322
323 /* Helper functions for memory allocation, don't use directly
324 */
325 void* __attribute__ ((__warn_unused_result__))
326 __mem_alloc (size_t len, size_t extra, size_t elsize, bool must);
327
328 void* __attribute__ ((__warn_unused_result__))
329 __mem_resize (void *p, size_t len, size_t cap, size_t elsize, bool must);
330
331 void
332 __mem_shrink (void *p, size_t len, size_t elsize);
333
334 /******************** Strings ********************/
335 /* Create new string
336 */
337 static inline char*
str_new(void)338 str_new (void) {
339 char *s = mem_resize((char*) NULL, 0, 1);
340 *s = '\0';
341 return s;
342 }
343
344 /* Create new string as a copy of existent string
345 */
346 static inline char*
str_dup(const char * s1)347 str_dup (const char *s1)
348 {
349 size_t len = strlen(s1);
350 char *s = mem_resize((char*) NULL, len, 1);
351 memcpy(s, s1, len + 1);
352 return s;
353 }
354
355 /* Get string length in bytes, not including terminating '\0'
356 */
357 static inline size_t
str_len(const char * s)358 str_len (const char *s)
359 {
360 return mem_len(s);
361 }
362
363 /* Create new string as a lowercase copy of existent string
364 */
365 char*
366 str_dup_tolower (const char *s1);
367
368 /* Create new string and print to it
369 */
370 char*
371 str_printf (const char *format, ...);
372
373 /* Create new string and print to it, va_list version
374 */
375 char*
376 str_vprintf (const char *format, va_list ap);
377
378 /* Truncate the string
379 */
380 static inline void
str_trunc(char * s)381 str_trunc (char *s)
382 {
383 mem_trunc(s);
384 *s = '\0';
385 }
386
387 /* Resize the string
388 *
389 * s1 must be previously created by some of str_XXX functions,
390 * s1 will be consumed and the new pointer will be returned
391 */
392 static inline char*
str_resize(char * s,size_t len)393 str_resize (char *s, size_t len)
394 {
395 s = mem_resize(s, len, 1);
396 s[len] = '\0';
397 return s;
398 }
399
400 /* Append memory to string:
401 * s1 += s2[:l2]
402 *
403 * s1 must be previously created by some of str_XXX functions,
404 * s1 will be consumed and the new pointer will be returned
405 */
406 static inline char*
str_append_mem(char * s1,const char * s2,size_t l2)407 str_append_mem (char *s1, const char *s2, size_t l2)
408 {
409 size_t l1 = str_len(s1);
410
411 s1 = mem_resize(s1, l1 + l2, 1);
412 memcpy(s1 + l1, s2, l2);
413 s1[l1+l2] = '\0';
414
415 return s1;
416 }
417
418 /* Append string to string:
419 * s1 += s2
420 *
421 * s1 must be previously created by some of str_XXX functions,
422 * s1 will be consumed and the new pointer will be returned
423 */
424 static inline char*
str_append(char * s1,const char * s2)425 str_append (char *s1, const char *s2)
426 {
427 return str_append_mem(s1, s2, strlen(s2));
428 }
429
430 /* Append character to string:
431 * s1 += c
432 *
433 * `s' must be previously created by some of str_XXX functions,
434 * `s' will be consumed and the new pointer will be returned
435 */
436 static inline char*
str_append_c(char * s,char c)437 str_append_c (char *s, char c)
438 {
439 return str_append_mem(s, &c, 1);
440 }
441
442 /* Append formatted string to string
443 *
444 * `s' must be previously created by some of str_XXX functions,
445 * `s' will be consumed and the new pointer will be returned
446 */
447 char*
448 str_append_printf (char *s, const char *format, ...);
449
450 /* Append formatted string to string -- va_list version
451 */
452 char*
453 str_append_vprintf (char *s, const char *format, va_list ap);
454
455 /* Assign value to string
456 *
457 * `s1' must be previously created by some of str_XXX functions,
458 * `s1' will be consumed and the new pointer will be returned
459 */
460 static inline char*
str_assign(char * s1,const char * s2)461 str_assign (char *s1, const char *s2)
462 {
463 mem_trunc(s1);
464 return str_append(s1, s2);
465 }
466
467 /* Concatenate several strings. Last pointer must be NULL.
468 * The returned pointer must be eventually freed by mem_free
469 */
470 char*
471 str_concat (const char *s, ...);
472
473 /* Make sure that string is terminated with the `c' character:
474 * if string is not empty and the last character is not `c`,
475 * append `c' to the string
476 *
477 * `s' must be previously created by some of str_XXX functions,
478 * `s' will be consumed and the new pointer will be returned
479 */
480 static inline char*
str_terminate(char * s,char c)481 str_terminate (char *s, char c)
482 {
483 if (s[0] != '\0' && s[str_len(s) - 1] != c) {
484 s = str_append_c(s, c);
485 }
486
487 return s;
488 }
489
490 /* Check if string has a specified prefix
491 */
492 bool
493 str_has_prefix (const char *s, const char *prefix);
494
495 /* Check if string has a specified suffix
496 */
497 bool
498 str_has_suffix (const char *s, const char *suffix);
499
500 /* Remove leading and trailing white space.
501 * This function modifies string in place, and returns pointer
502 * to original string, for convenience
503 */
504 char*
505 str_trim (char *s);
506
507 /******************** NULL-terminated pointer arrays ********************/
508 /* Create NULL-terminated array of pointers of type *T
509 */
510 #define ptr_array_new(T) mem_resize((T*) NULL, 0, 1)
511
512 /* Append pointer to the NULL-terminated array of pointers.
513 * Returns new, potentially reallocated array
514 */
515 #define ptr_array_append(a,p) \
516 ((__typeof__(a)) __ptr_array_append((void**)a, p))
517
518 /* Truncate NULL-terminated array of pointers
519 */
520 #define ptr_array_trunc(a) \
521 do { \
522 mem_trunc(a); \
523 a[0] = NULL; \
524 } while(0)
525
526 /* Find pointer within array of pointers.
527 * Return non-negative index if pointer was found, -1 otherwise
528 */
529 #define ptr_array_find(a,p) __ptr_array_find((void**) a, p)
530
531 /* Delete element at given index.
532 * Returns value of deleted pointer or NULL, if index is out of range
533 */
534 #define ptr_array_del(a,i) \
535 ((__typeof__(*a)) __ptr_array_del((void**) a, i))
536
537 /* Helper function for ptr_array_append, don't use directly
538 */
539 static inline void**
__ptr_array_append(void ** a,void * p)540 __ptr_array_append (void **a, void *p)
541 {
542 size_t len = mem_len(a) + 1;
543 a = mem_resize(a, len, 1);
544 a[len - 1] = p;
545 a[len] = NULL;
546 return a;
547 }
548
549 /* Helper function for ptr_array_find, don't use directly
550 */
551 static inline int
__ptr_array_find(void ** a,void * p)552 __ptr_array_find (void **a, void *p)
553 {
554 size_t len = mem_len(a), i;
555
556 for (i = 0; i < len; i ++) {
557 if (a[i] == p) {
558 return (int) i;
559 }
560 }
561
562 return -1;
563 }
564
565 /* Helper function for ptr_array_del, don't use directly
566 */
567 static inline void*
__ptr_array_del(void ** a,int i)568 __ptr_array_del (void **a, int i)
569 {
570 size_t len = mem_len(a);
571 void *p;
572
573 if (i < 0 || i >= (int) len) {
574 return NULL;
575 }
576
577 len --;
578 p = a[i];
579 memmove(&a[i], &a[i + 1], sizeof(void*) * (len - i));
580 mem_shrink(a, len);
581 a[len] = NULL;
582
583 return p;
584 }
585
586 /******************** Safe ctype macros ********************/
587 #define safe_isspace(c) isspace((unsigned char) c)
588 #define safe_isxdigit(c) isxdigit((unsigned char) c)
589 #define safe_toupper(c) toupper((unsigned char) c)
590 #define safe_tolower(c) tolower((unsigned char) c)
591
592 /******************** OS Facilities ********************/
593 /* The following macros, if defined, indicate that OS
594 * has a particular features:
595 *
596 * OS_HAVE_EVENTFD - Linux-like eventfd (2)
597 * OS_HAVE_RTNETLINK - Linux-like rtnetlink (7)
598 * OS_HAVE_AF_ROUTE - BSD-like AF_ROUTE
599 * OS_HAVE_LINUX_PROCFS - Linux-style procfs
600 * OS_HAVE_IP_MREQN - OS defines struct ip_mreqn
601 * OS_HAVE_ENDIAN_H - #include <endian.h> works
602 * OS_HAVE_SYS_ENDIAN_H - #include <sys/endian.h> works
603 */
604 #ifdef __linux__
605 # define OS_HAVE_EVENTFD 1
606 # define OS_HAVE_RTNETLINK 1
607 # define OS_HAVE_LINUX_PROCFS 1
608 # define OS_HAVE_IP_MREQN 1
609 # define OS_HAVE_ENDIAN_H 1
610 #endif
611
612 #ifdef BSD
613 # define OS_HAVE_AF_ROUTE 1
614 # ifdef __FreeBSD__
615 # define OS_HAVE_SYS_ENDIAN_H 1
616 # else
617 # define OS_HAVE_ENDIAN_H 1
618 # endif
619 #endif
620
621 /* Get user's home directory. There is no need to
622 * free the returned string
623 *
624 * May return NULL in a case of error
625 */
626 const char *
627 os_homedir (void);
628
629 /* Get base name of the calling program.
630 * There is no need to free the returned string
631 *
632 * May return NULL in a case of error
633 */
634 const char*
635 os_progname (void);
636
637 /* Make directory with parents
638 */
639 int
640 os_mkdir (const char *path, mode_t mode);
641
642 /******************** Error handling ********************/
643 /* Type error represents an error. Its value either NULL,
644 * which indicates "no error" condition, or some opaque
645 * non-null pointer, which can be converted to string
646 * with textual description of the error, using the ESTRING()
647 * function
648 *
649 * Caller should not attempt to free the memory, referred
650 * by error or string, obtained from an error using the
651 * ESTRING() function
652 */
653 typedef struct error_s *error;
654
655 /* Standard errors
656 */
657 extern error ERROR_ENOMEM;
658
659 /* Construct error from a string
660 */
661 static inline error
ERROR(const char * s)662 ERROR (const char *s)
663 {
664 return (error) s;
665 }
666
667 /* Obtain textual representation of the error
668 */
669 static inline const char*
ESTRING(error err)670 ESTRING (error err)
671 {
672 return (const char*) err;
673 }
674
675 /******************** Various identifiers ********************/
676 /* ID_PROTO represents protocol identifier
677 */
678 typedef enum {
679 ID_PROTO_UNKNOWN = -1,
680 ID_PROTO_ESCL,
681 ID_PROTO_WSD,
682
683 NUM_ID_PROTO
684 } ID_PROTO;
685
686 /* id_proto_name returns protocol name
687 * For unknown ID returns NULL
688 */
689 const char*
690 id_proto_name (ID_PROTO proto);
691
692 /* id_proto_by_name returns protocol identifier by name
693 * For unknown name returns ID_PROTO_UNKNOWN
694 */
695 ID_PROTO
696 id_proto_by_name (const char* name);
697
698 /* ID_SOURCE represents scanning source
699 */
700 typedef enum {
701 ID_SOURCE_UNKNOWN = -1,
702 ID_SOURCE_PLATEN,
703 ID_SOURCE_ADF_SIMPLEX,
704 ID_SOURCE_ADF_DUPLEX,
705
706 NUM_ID_SOURCE
707 } ID_SOURCE;
708
709 /* id_source_sane_name returns SANE name for the source
710 * For unknown ID returns NULL
711 */
712 const char*
713 id_source_sane_name (ID_SOURCE id);
714
715 /* id_source_by_sane_name returns ID_SOURCE by its SANE name
716 * For unknown name returns ID_SOURCE_UNKNOWN
717 */
718 ID_SOURCE
719 id_source_by_sane_name (const char *name);
720
721 /* ID_COLORMODE represents color mode
722 */
723 typedef enum {
724 ID_COLORMODE_UNKNOWN = -1,
725 ID_COLORMODE_COLOR,
726 ID_COLORMODE_GRAYSCALE,
727 ID_COLORMODE_BW1,
728
729 NUM_ID_COLORMODE
730 } ID_COLORMODE;
731
732 /* id_colormode_sane_name returns SANE name for the color mode
733 * For unknown ID returns NULL
734 */
735 const char*
736 id_colormode_sane_name (ID_COLORMODE id);
737
738 /* id_colormode_by_sane_name returns ID_COLORMODE by its SANE name
739 * For unknown name returns ID_COLORMODE_UNKNOWN
740 */
741 ID_COLORMODE
742 id_colormode_by_sane_name (const char *name);
743
744 /* ID_FORMAT represents image format
745 */
746 typedef enum {
747 ID_FORMAT_UNKNOWN = -1,
748 ID_FORMAT_JPEG,
749 ID_FORMAT_TIFF,
750 ID_FORMAT_PNG,
751 ID_FORMAT_PDF,
752 ID_FORMAT_BMP,
753
754 NUM_ID_FORMAT
755 } ID_FORMAT;
756
757 /* id_format_mime_name returns MIME name for the image format
758 */
759 const char*
760 id_format_mime_name (ID_FORMAT id);
761
762 /* id_format_by_mime_name returns ID_FORMAT by its MIME name
763 * For unknown name returns ID_FORMAT_UNKNOWN
764 */
765 ID_FORMAT
766 id_format_by_mime_name (const char *name);
767
768 /* if_format_short_name returns short name for ID_FORMAT
769 */
770 const char*
771 id_format_short_name (ID_FORMAT id);
772
773 /******************** Device ID ********************/
774 /* Allocate unique device ID
775 */
776 unsigned int
777 devid_alloc (void);
778
779 /* Free device ID
780 */
781 void
782 devid_free (unsigned int id);
783
784 /* Initialize device ID allocator
785 */
786 void
787 devid_init (void);
788
789 /******************** Random bytes ********************/
790 /* Get N random bytes
791 */
792 void
793 rand_bytes (void *buf, size_t n);
794
795 /* Initialize random bytes generator
796 */
797 SANE_Status
798 rand_init (void);
799
800 /* Cleanup random bytes generator
801 */
802 void
803 rand_cleanup (void);
804
805 /******************** UUID utilities ********************/
806 /* Type uuid represents a random UUID string.
807 *
808 * It is wrapped into struct, so it can be returned
809 * by value, without need to mess with memory allocation
810 */
811 typedef struct {
812 char text[sizeof("urn:uuid:ede05377-460e-4b4a-a5c0-423f9e02e8fa")];
813 } uuid;
814
815 /* Check if uuid is valid
816 */
817 static inline bool
uuid_valid(uuid u)818 uuid_valid (uuid u)
819 {
820 return u.text[0] != '\0';
821 }
822
823 /* Generate random UUID. Generated UUID has a following form:
824 * urn:uuid:ede05377-460e-4b4a-a5c0-423f9e02e8fa
825 */
826 uuid
827 uuid_rand (void);
828
829 /* Parse UUID. This function ignores all "decorations", like
830 * urn:uuid: prefix and so on, and takes only hexadecimal digits
831 * into considerations
832 *
833 * Check the returned uuid with uuid_valid() for possible parse errors
834 */
835 uuid
836 uuid_parse (const char *in);
837
838 /* Generate uuid by cryptographically cacheing input string
839 */
840 uuid
841 uuid_hash (const char *s);
842
843 /* Compare two uuids
844 */
845 static inline bool
uuid_equal(uuid u1,uuid u2)846 uuid_equal (uuid u1, uuid u2)
847 {
848 return !strcmp(u1.text, u2.text);
849 }
850
851 /******************** Generic .INI file parser ********************/
852 /* Types of .INI file records
853 */
854 typedef enum {
855 INIFILE_SECTION, /* The [section name] string */
856 INIFILE_VARIABLE, /* The variable = value string */
857 INIFILE_COMMAND, /* command param1 param2 ... */
858 INIFILE_SYNTAX /* The syntax error */
859 } INIFILE_RECORD;
860
861 /* .INI file record
862 */
863 typedef struct {
864 INIFILE_RECORD type; /* Record type */
865 const char *section; /* Section name */
866 const char *variable; /* Variable name */
867 const char *value; /* Variable value */
868 const char **tokv; /* Value split to tokens */
869 unsigned int tokc; /* Count of strings in tokv */
870 const char *file; /* File name */
871 unsigned int line; /* File line */
872 } inifile_record;
873
874 /* .INI file (opaque)
875 */
876 typedef struct {
877 const char *file; /* File name */
878 unsigned int line; /* File handle */
879 FILE *fp; /* File pointer */
880
881 bool tk_open; /* Token is currently open */
882 char *tk_buffer; /* Parser buffer, tokenized */
883 unsigned int *tk_offsets; /* Tokens offsets */
884 unsigned int tk_count; /* Tokens count */
885
886 char *buffer; /* Parser buffer */
887 char *section; /* Section name string */
888 char *variable; /* Variable name string */
889 char *value; /* Value string */
890 inifile_record record; /* Record buffer */
891 } inifile;
892
893 /* Open the .INI file
894 */
895 inifile*
896 inifile_open (const char *name);
897
898 /* Close the .INI file
899 */
900 void
901 inifile_close (inifile *file);
902
903 /* Read next record
904 */
905 const inifile_record*
906 inifile_read (inifile *file);
907
908 /* Match name of section of variable
909 * - match is case-insensitive
910 * - difference in amount of free space is ignored
911 * - leading and trailing space is ignored
912 */
913 bool
914 inifile_match_name (const char *n1, const char *n2);
915
916 /******************** Utility functions for IP addresses ********************/
917 /* Address string, wrapped into structure so can
918 * be passed by value
919 */
920 typedef struct {
921 /* Holds sun_path from sockaddr_un plus a null byte. */
922 char text[109];
923 } ip_straddr;
924
925 /* Format ip_straddr from IP address (struct in_addr or struct in6_addr)
926 * af must be AF_INET or AF_INET6
927 */
928 ip_straddr
929 ip_straddr_from_ip (int af, const void *addr);
930
931 /* Format ip_straddr from struct sockaddr.
932 * AF_INET, AF_INET6, and AF_UNIX are supported
933 *
934 * If `withzone' is true, zone suffix will be appended, when appropriate
935 */
936 ip_straddr
937 ip_straddr_from_sockaddr(const struct sockaddr *addr, bool withzone);
938
939 /* Format ip_straddr from struct sockaddr.
940 * AF_INET, AF_INET6, and AF_UNIX are supported
941 *
942 * Port will not be appended, if it matches provided default port
943 * If `withzone' is true, zone suffix will be appended, when appropriate
944 */
945 ip_straddr
946 ip_straddr_from_sockaddr_dport (const struct sockaddr *addr,
947 int dport, bool withzone);
948
949 /* Check if address is link-local
950 * af must be AF_INET or AF_INET6
951 */
952 bool
953 ip_is_linklocal (int af, const void *addr);
954
955 /* Check if sockaddr is link-local
956 */
957 bool
958 ip_sockaddr_is_linklocal (const struct sockaddr *addr);
959
960 /* Check if address is loopback
961 * af must be AF_INET or AF_INET6
962 */
963 bool
964 ip_is_loopback (int af, const void *addr);
965
966 /* ip_addr represents IPv4 or IPv6 address
967 */
968 typedef struct {
969 int af; /* AF_INET or AF_INET6 */
970 int ifindex; /* For IPv6 link-local addresses */
971 union {
972 struct in_addr v4; /* IPv4 address */
973 struct in6_addr v6; /* IPv4 address */
974 } ip;
975 } ip_addr;
976
977 /* Make ip_addr
978 */
979 static inline ip_addr
ip_addr_make(int ifindex,int af,const void * addr)980 ip_addr_make (int ifindex, int af, const void *addr)
981 {
982 ip_addr ip_addr;
983
984 memset(&ip_addr, 0, sizeof(ip_addr));
985 ip_addr.af = af;
986
987 switch (ip_addr.af) {
988 case AF_INET:
989 memcpy(&ip_addr.ip.v4, addr, 4);
990 break;
991
992 case AF_INET6:
993 memcpy(&ip_addr.ip, addr, 16);
994 if (ip_is_linklocal(AF_INET6, &ip_addr.ip.v6)) {
995 ip_addr.ifindex = ifindex;
996 }
997 break;
998 }
999
1000 return ip_addr;
1001 }
1002
1003 /* Extract ip_addr from sockaddr
1004 */
1005 static inline ip_addr
ip_addr_from_sockaddr(const struct sockaddr * sockaddr)1006 ip_addr_from_sockaddr (const struct sockaddr *sockaddr)
1007 {
1008 ip_addr addr;
1009
1010 memset(&addr, 0, sizeof(addr));
1011 addr.af = sockaddr->sa_family;
1012
1013 switch (addr.af) {
1014 case AF_INET:
1015 addr.ip.v4 = ((struct sockaddr_in*) sockaddr)->sin_addr;
1016 break;
1017
1018 case AF_INET6:
1019 addr.ip.v6 = ((struct sockaddr_in6*) sockaddr)->sin6_addr;
1020 if (ip_is_linklocal(AF_INET6, &addr.ip.v6)) {
1021 addr.ifindex = ((struct sockaddr_in6*) sockaddr)->sin6_scope_id;
1022 }
1023 break;
1024 }
1025
1026 return addr;
1027 }
1028
1029 /* Format ip_addr into ip_straddr
1030 */
1031 ip_straddr
1032 ip_addr_to_straddr (ip_addr addr, bool withzone);
1033
1034 /* Check if two addresses are equal
1035 */
1036 static inline bool
ip_addr_equal(ip_addr a1,ip_addr a2)1037 ip_addr_equal (ip_addr a1, ip_addr a2)
1038 {
1039 if (a1.af != a2.af) {
1040 return false;
1041 }
1042
1043 switch (a1.af) {
1044 case AF_INET:
1045 return a1.ip.v4.s_addr == a2.ip.v4.s_addr;
1046 case AF_INET6:
1047 return a1.ifindex == a2.ifindex &&
1048 !memcmp(a1.ip.v6.s6_addr, a2.ip.v6.s6_addr, 16);
1049 }
1050
1051 return false;
1052 }
1053
1054 /* ip_network represents IPv4 or IPv6 network (i.e., address with mask)
1055 */
1056 typedef struct {
1057 ip_addr addr; /* Network address */
1058 int mask; /* Network mask */
1059 } ip_network;
1060
1061 /* Format ip_network into ip_straddr
1062 */
1063 ip_straddr
1064 ip_network_to_straddr (ip_network net);
1065
1066 /* Check if ip_network contains ip_addr
1067 */
1068 bool
1069 ip_network_contains (ip_network net, ip_addr addr);
1070
1071 /* ip_addr_set represents a set of IP addresses
1072 */
1073 typedef struct ip_addrset ip_addrset;
1074
1075 /* Create new ip_addrset
1076 */
1077 ip_addrset*
1078 ip_addrset_new (void);
1079
1080 /* Free ip_addrset
1081 */
1082 void
1083 ip_addrset_free (ip_addrset *addrset);
1084
1085 /* Check if address is in set
1086 */
1087 bool
1088 ip_addrset_lookup (const ip_addrset *addrset, ip_addr addr);
1089
1090 /* Add address to the set. Returns true, if address was
1091 * actually added, false if it was already in the set
1092 */
1093 bool
1094 ip_addrset_add (ip_addrset *addrset, ip_addr addr);
1095
1096 /* Add address to the set without checking for duplicates
1097 */
1098 void
1099 ip_addrset_add_unsafe (ip_addrset *addrset, ip_addr addr);
1100
1101 /* Del address from the set.
1102 */
1103 void
1104 ip_addrset_del (ip_addrset *addrset, ip_addr addr);
1105
1106 /* Delete all addresses from the set
1107 */
1108 void
1109 ip_addrset_purge (ip_addrset *addrset);
1110
1111 /* Merge two sets:
1112 * addrset += addrset2
1113 */
1114 void
1115 ip_addrset_merge (ip_addrset *addrset, const ip_addrset *addrset2);
1116
1117 /* Get access to array of addresses in the set
1118 */
1119 const ip_addr*
1120 ip_addrset_addresses (const ip_addrset *addrset, size_t *count);
1121
1122 /* Check if two address sets are intersecting
1123 */
1124 bool
1125 ip_addrset_is_intersect (const ip_addrset *set, const ip_addrset *set2);
1126
1127 /* Check if some of addresses in the address set is on the
1128 * given network
1129 */
1130 bool
1131 ip_addrset_on_network (const ip_addrset *set, ip_network net);
1132
1133 /* Create user-friendly string out of set of addresses, containing
1134 * in the ip_addrset:
1135 * * addresses are sorted, IP4 addresses goes first
1136 * * link-local addresses are skipped, if there are non-link-local ones
1137 */
1138 char*
1139 ip_addrset_friendly_str (const ip_addrset *set, char *s);
1140
1141 /******************** Network interfaces addresses ********************/
1142 /* Network interface name, wrapped into structure, so
1143 * it can be passed by value
1144 */
1145 typedef struct {
1146 char text[32];
1147 } netif_name;
1148
1149 /* Network interface address
1150 */
1151 typedef struct netif_addr netif_addr;
1152 struct netif_addr {
1153 netif_addr *next; /* Next address in the list */
1154 int ifindex; /* Interface index */
1155 netif_name ifname; /* Interface name, for logging */
1156 bool ipv6; /* This is an IPv6 address */
1157 void *data; /* Placeholder for user data */
1158 char straddr[64]; /* Address string */
1159 union {
1160 struct in_addr v4; /* IPv4 address */
1161 struct in6_addr v6; /* IPv6 address */
1162 } ip;
1163 };
1164
1165 /* NETIF_DISTANCE represents a distance to the target address
1166 */
1167 typedef enum {
1168 NETIF_DISTANCE_LOOPBACK, /* Target address is host's local address */
1169 NETIF_DISTANCE_DIRECT, /* Target is on a local network */
1170 NETIF_DISTANCE_ROUTED /* Target is behind a router */
1171 } NETIF_DISTANCE;
1172
1173 /* Get distance to the target address
1174 */
1175 NETIF_DISTANCE
1176 netif_distance_get (const struct sockaddr *addr);
1177
1178 /* Check that interface has non-link-local address
1179 * of particular address family
1180 */
1181 bool
1182 netif_has_non_link_local_addr (int af, int ifindex);
1183
1184 /* Compare addresses by distance. Returns:
1185 * <0, if addr1 is closer that addr2
1186 * >0, if addr2 is farther that addr2
1187 * 0 if distance is equal
1188 */
1189 static inline int
netif_distance_cmp(const struct sockaddr * addr1,const struct sockaddr * addr2)1190 netif_distance_cmp (const struct sockaddr *addr1, const struct sockaddr *addr2)
1191 {
1192 int d1 = (int) netif_distance_get(addr1);
1193 int d2 = (int) netif_distance_get(addr2);
1194
1195 return d1 - d2;
1196 }
1197
1198 /* Get list of network interfaces addresses
1199 * The returned list is sorted
1200 */
1201 netif_addr*
1202 netif_addr_list_get (void);
1203
1204 /* Free list of network interfaces addresses
1205 */
1206 void
1207 netif_addr_list_free (netif_addr *list);
1208
1209 /* netif_diff represents a difference between two
1210 * lists of network interface addresses
1211 */
1212 typedef struct {
1213 netif_addr *added, *removed; /* What was added/removed */
1214 netif_addr *preserved;
1215 } netif_diff;
1216
1217 /* Compute a difference between two lists of addresses.
1218 *
1219 * It works by tossing nodes between 3 output lists:
1220 * * if node is present in list2 only, it is moved
1221 * to netif_diff.added
1222 * * if node is present in list1 only, it is moved
1223 * to netif_diff.removed
1224 * * if node is present in both lists, node from
1225 * list1 is moved to preserved, and node from
1226 * list2 is released
1227 *
1228 * It assumes, both lists are sorted, as returned
1229 * by netif_addr_get(). Returned lists are also sorted
1230 */
1231 netif_diff
1232 netif_diff_compute (netif_addr *list1, netif_addr *list2);
1233
1234 /* Merge two lists of addresses
1235 *
1236 * Input lists are consumed and new list is created.
1237 *
1238 * Input lists are assumed to be sorted, and output
1239 * list will be sorted as well
1240 */
1241 netif_addr*
1242 netif_addr_list_merge (netif_addr *list1, netif_addr *list2);
1243
1244 /* Network interfaces addresses change notifier
1245 */
1246 typedef struct netif_notifier netif_notifier;
1247
1248 /* Create netif_notifier
1249 */
1250 netif_notifier*
1251 netif_notifier_create (void (*callback) (void*), void *data);
1252
1253 /* Destroy netif_notifier
1254 */
1255 void
1256 netif_notifier_free (netif_notifier *notifier);
1257
1258 /* Initialize network interfaces monitoring
1259 */
1260 SANE_Status
1261 netif_init (void);
1262
1263 /* Cleanup network interfaces monitoring
1264 */
1265 void
1266 netif_cleanup (void);
1267
1268 /******************** Configuration file loader ********************/
1269 /* Device URI for manually disabled device
1270 */
1271 #define CONF_DEVICE_DISABLE "disable"
1272
1273 /* Device configuration, for manually added devices
1274 */
1275 typedef struct conf_device conf_device;
1276 struct conf_device {
1277 unsigned int devid; /* Device ident */
1278 const char *name; /* Device name */
1279 ID_PROTO proto; /* Protocol to use */
1280 http_uri *uri; /* Device URI, parsed; NULL if device disabled */
1281 conf_device *next; /* Next device in the list */
1282 };
1283
1284 /* WSDD_MODE represents WS-Discovery mode
1285 */
1286 typedef enum {
1287 WSDD_FAST, /* Use hints from DNS-SD to speed up WSDD */
1288 WSDD_FULL, /* Full discovery, slow and fair */
1289 WSDD_OFF /* Disable WSDD */
1290 } WSDD_MODE;
1291
1292 /* Device blacklist entry
1293 */
1294 typedef struct conf_blacklist conf_blacklist;
1295 struct conf_blacklist {
1296 const char *model; /* If not NULL, match by model */
1297 const char *name; /* If not NULL, match by network name */
1298 ip_network net; /* if net.addr.af != AF_UNSPEC, match by net */
1299 conf_blacklist *next; /* Next entry in the list */
1300 };
1301
1302 /* Backend configuration
1303 */
1304 typedef struct {
1305 bool dbg_enabled; /* Debugging enabled */
1306 const char *dbg_trace; /* Trace directory */
1307 conf_device *devices; /* Manually configured devices */
1308 bool discovery; /* Scanners discovery enabled */
1309 bool model_is_netname; /* Use network name instead of model */
1310 bool proto_auto; /* Auto protocol selection */
1311 WSDD_MODE wsdd_mode; /* WS-Discovery mode */
1312 const char *socket_dir; /* Directory for AF_UNIX sockets */
1313 conf_blacklist *blacklist; /* Devices blacklisted for discovery */
1314 } conf_data;
1315
1316 #define CONF_INIT { \
1317 .dbg_enabled = false, \
1318 .dbg_trace = NULL, \
1319 .devices = NULL, \
1320 .discovery = true, \
1321 .model_is_netname = true, \
1322 .proto_auto = true, \
1323 .wsdd_mode = WSDD_FAST, \
1324 .socket_dir = NULL \
1325 }
1326
1327 extern conf_data conf;
1328
1329 /* Load configuration. It updates content of a global conf variable
1330 */
1331 void
1332 conf_load (void);
1333
1334 /* Free resources, allocated by conf_load, and reset configuration
1335 * data into initial state
1336 */
1337 void
1338 conf_unload (void);
1339
1340 /******************** Pollable events ********************/
1341 /* The pollable event
1342 *
1343 * Pollable events allow to wait until some event happens
1344 * and can be used in combination with select()/poll()
1345 * system calls
1346 */
1347 typedef struct pollable pollable;
1348
1349 /* Create new pollable event
1350 */
1351 pollable*
1352 pollable_new (void);
1353
1354 /* Free pollable event
1355 */
1356 void
1357 pollable_free (pollable *p);
1358
1359 /* Get file descriptor for poll()/select().
1360 *
1361 * When pollable event becomes "ready", this file descriptor
1362 * becomes readable from the select/poll point of view
1363 */
1364 int
1365 pollable_get_fd (pollable *p);
1366
1367 /* Make pollable event "ready"
1368 */
1369 void
1370 pollable_signal (pollable *p);
1371
1372 /* Make pollable event "not ready"
1373 */
1374 void
1375 pollable_reset (pollable *p);
1376
1377 /* Wait until pollable event is ready
1378 */
1379 void
1380 pollable_wait (pollable *p);
1381
1382 /******************** Time stamps ********************/
1383 /* timestamp represents a monotonic time, in milliseconds
1384 */
1385 typedef int64_t timestamp;
1386
1387 /* timestamp_now() returns a current time as timestamp
1388 */
1389 static inline timestamp
timestamp_now(void)1390 timestamp_now (void)
1391 {
1392 struct timespec t;
1393
1394 clock_gettime(CLOCK_MONOTONIC, &t);
1395 return (timestamp) t.tv_sec * 1000 + (timestamp) t.tv_nsec / 1000000;
1396 }
1397
1398 /******************** Event loop ********************/
1399 /* Initialize event loop
1400 */
1401 SANE_Status
1402 eloop_init (void);
1403
1404 /* Cleanup event loop
1405 */
1406 void
1407 eloop_cleanup (void);
1408
1409 /* Add start/stop callback. This callback is called
1410 * on a event loop thread context, once when event
1411 * loop is started, and second time when it is stopped
1412 *
1413 * Start callbacks are called in the same order as
1414 * they were added. Stop callbacks are called in a
1415 * reverse order
1416 */
1417 void
1418 eloop_add_start_stop_callback (void (*callback) (bool start));
1419
1420 /* Start event loop thread.
1421 */
1422 void
1423 eloop_thread_start (void);
1424
1425 /* Stop event loop thread and wait until its termination
1426 */
1427 void
1428 eloop_thread_stop (void);
1429
1430 /* Acquire event loop mutex
1431 */
1432 void
1433 eloop_mutex_lock (void);
1434
1435 /* Release event loop mutex
1436 */
1437 void
1438 eloop_mutex_unlock (void);
1439
1440 /* Wait on conditional variable under the event loop mutex
1441 */
1442 void
1443 eloop_cond_wait (pthread_cond_t *cond);
1444
1445 /* Get AvahiPoll that runs in event loop thread
1446 */
1447 const AvahiPoll*
1448 eloop_poll_get (void);
1449
1450 /* Call function on a context of event loop thread
1451 * The returned value can be supplied as a `callid'
1452 * parameter for the eloop_call_cancel() function
1453 */
1454 uint64_t
1455 eloop_call (void (*func)(void*), void *data);
1456
1457 /* Cancel pending eloop_call
1458 *
1459 * This is safe to cancel already finished call (at this
1460 * case nothing will happen)
1461 */
1462 void
1463 eloop_call_cancel (uint64_t callid);
1464
1465 /* Event notifier. Calls user-defined function on a context
1466 * of event loop thread, when event is triggered. This is
1467 * safe to trigger the event from a context of any thread
1468 * or even from a signal handler
1469 */
1470 typedef struct eloop_event eloop_event;
1471
1472 /* Create new event notifier. May return NULL
1473 */
1474 eloop_event*
1475 eloop_event_new (void (*callback)(void *), void *data);
1476
1477 /* Destroy event notifier
1478 */
1479 void
1480 eloop_event_free (eloop_event *event);
1481
1482 /* Trigger an event
1483 */
1484 void
1485 eloop_event_trigger (eloop_event *event);
1486
1487 /* Timer. Calls user-defined function after a specified
1488 * interval
1489 */
1490 typedef struct eloop_timer eloop_timer;
1491
1492 /* Create new timer. Timeout is in milliseconds
1493 */
1494 eloop_timer*
1495 eloop_timer_new (int timeout, void (*callback)(void *), void *data);
1496
1497 /* Cancel a timer
1498 *
1499 * Caller SHOULD NOT cancel expired timer (timer with called
1500 * callback) -- this is done automatically
1501 */
1502 void
1503 eloop_timer_cancel (eloop_timer *timer);
1504
1505 /* eloop_fdpoll notifies user when file becomes
1506 * readable, writable or both, depending on its
1507 * event mask
1508 */
1509 typedef struct eloop_fdpoll eloop_fdpoll;
1510
1511 /* Mask of file events user interested in
1512 */
1513 typedef enum {
1514 ELOOP_FDPOLL_READ = (1 << 0),
1515 ELOOP_FDPOLL_WRITE = (1 << 1),
1516 ELOOP_FDPOLL_BOTH = ELOOP_FDPOLL_READ | ELOOP_FDPOLL_WRITE
1517 } ELOOP_FDPOLL_MASK;
1518
1519 /* Convert ELOOP_FDPOLL_MASK to string. Used for logging.
1520 */
1521 const char*
1522 eloop_fdpoll_mask_str (ELOOP_FDPOLL_MASK mask);
1523
1524 /* Create eloop_fdpoll
1525 *
1526 * Callback will be called, when file will be ready for read/write/both,
1527 * depending on mask
1528 *
1529 * Initial mask value is 0, and it can be changed, using
1530 * eloop_fdpoll_set_mask() function
1531 */
1532 eloop_fdpoll*
1533 eloop_fdpoll_new (int fd,
1534 void (*callback) (int, void*, ELOOP_FDPOLL_MASK), void *data);
1535
1536 /* Destroy eloop_fdpoll
1537 */
1538 void
1539 eloop_fdpoll_free (eloop_fdpoll *fdpoll);
1540
1541 /* Set eloop_fdpoll event mask. It returns a previous value of event mask
1542 */
1543 ELOOP_FDPOLL_MASK
1544 eloop_fdpoll_set_mask (eloop_fdpoll *fdpoll, ELOOP_FDPOLL_MASK mask);
1545
1546 /* Format error string, as printf() does and save result
1547 * in the memory, owned by the event loop
1548 *
1549 * Caller should not free returned string. This is safe
1550 * to use the returned string as an argument to the
1551 * subsequent eloop_eprintf() call.
1552 *
1553 * The returned string remains valid until next call
1554 * to eloop_eprintf(), which makes it usable to
1555 * report errors up by the stack. However, it should
1556 * not be assumed, that the string will remain valid
1557 * on a next eloop roll, so don't save this string
1558 * anywhere, if you need to do so, create a copy!
1559 */
1560 error
1561 eloop_eprintf(const char *fmt, ...);
1562
1563 /******************** HTTP Client ********************/
1564 /* Create new URI, by parsing URI string
1565 */
1566 http_uri*
1567 http_uri_new (const char *str, bool strip_fragment);
1568
1569 /* Clone an URI
1570 */
1571 http_uri*
1572 http_uri_clone (const http_uri *old);
1573
1574 /* Create URI, relative to base URI. If `path_only' is
1575 * true, scheme, host and port are taken from the
1576 * base URI
1577 */
1578 http_uri*
1579 http_uri_new_relative (const http_uri *base, const char *path,
1580 bool strip_fragment, bool path_only);
1581
1582 /* Free the URI
1583 */
1584 void
1585 http_uri_free (http_uri *uri);
1586
1587 /* Get URI string
1588 */
1589 const char*
1590 http_uri_str (http_uri *uri);
1591
1592 /* Get URI's host address. If Host address is not literal, returns NULL
1593 */
1594 const struct sockaddr*
1595 http_uri_addr (http_uri *uri);
1596
1597 /* Get URI's address family. May return AF_UNSPEC,
1598 * if host address is not literal
1599 */
1600 static inline int
http_uri_af(http_uri * uri)1601 http_uri_af (http_uri *uri)
1602 {
1603 const struct sockaddr *addr = http_uri_addr(uri);
1604 return addr ? addr->sa_family : AF_UNSPEC;
1605 }
1606
1607 /* Get URI path
1608 */
1609 const char*
1610 http_uri_get_path (const http_uri *uri);
1611
1612 /* Set URI path
1613 */
1614 void
1615 http_uri_set_path (http_uri *uri, const char *path);
1616
1617 /* Get URI host. It returns only host name, port number is
1618 * not included.
1619 *
1620 * IPv6 literal addresses are returned in square brackets
1621 * (i.e., [fe80::217:c8ff:fe7b:6a91%4])
1622 *
1623 * Note, the subsequent modifications of URI, such as http_uri_fix_host(),
1624 * http_uri_fix_ipv6_zone() etc, may make the returned string invalid,
1625 * so if you need to keep it for a long time, better make a copy
1626 */
1627 const char*
1628 http_uri_get_host (const http_uri *uri);
1629
1630 /* Fix URI host: if `match` is NULL or uri's host matches `match`,
1631 * replace uri's host and port with values taken from the base_uri
1632 */
1633 void
1634 http_uri_fix_host (http_uri *uri, const http_uri *base_uri, const char *match);
1635
1636 /* Fix IPv6 address zone suffix
1637 */
1638 void
1639 http_uri_fix_ipv6_zone (http_uri *uri, int ifindex);
1640
1641 /* Strip zone suffix from literal IPv6 host address
1642 *
1643 * If address is not IPv6 or doesn't have zone suffix, it is
1644 * not changed
1645 */
1646 void
1647 http_uri_strip_zone_suffux (http_uri *uri);
1648
1649 /* Make sure URI's path ends with the slash character
1650 */
1651 void
1652 http_uri_fix_end_slash (http_uri *uri);
1653
1654 /* Check if 2 URIs are equal
1655 */
1656 bool
1657 http_uri_equal (const http_uri *uri1, const http_uri *uri2);
1658
1659 /* HTTP data
1660 */
1661 typedef struct {
1662 const char *content_type; /* Normalized: low-case with stripped directives */
1663 const void *bytes; /* Data bytes */
1664 size_t size; /* Data size */
1665 } http_data;
1666
1667 /* Ref http_data
1668 */
1669 http_data*
1670 http_data_ref (http_data *data);
1671
1672 /* Unref http_data
1673 */
1674 void
1675 http_data_unref (http_data *data);
1676
1677 /* http_data_queue represents a queue of http_data items
1678 */
1679 typedef struct http_data_queue http_data_queue;
1680
1681 /* Create new http_data_queue
1682 */
1683 http_data_queue*
1684 http_data_queue_new (void);
1685
1686 /* Destroy http_data_queue
1687 */
1688 void
1689 http_data_queue_free (http_data_queue *queue);
1690
1691 /* Push item into the http_data_queue.
1692 */
1693 void
1694 http_data_queue_push (http_data_queue *queue, http_data *data);
1695
1696 /* Pull an item from the http_data_queue. Returns NULL if queue is empty
1697 */
1698 http_data*
1699 http_data_queue_pull (http_data_queue *queue);
1700
1701 /* Get queue length
1702 */
1703 int
1704 http_data_queue_len (const http_data_queue *queue);
1705
1706 /* Check if queue is empty
1707 */
1708 static inline bool
http_data_queue_empty(const http_data_queue * queue)1709 http_data_queue_empty (const http_data_queue *queue)
1710 {
1711 return http_data_queue_len(queue) == 0;
1712 }
1713
1714 /* Purge the queue
1715 */
1716 void
1717 http_data_queue_purge (http_data_queue *queue);
1718
1719 /* Type http_client represents HTTP client instance
1720 */
1721 typedef struct http_client http_client;
1722
1723 /* Create new http_client
1724 */
1725 http_client*
1726 http_client_new (log_ctx *log, void *ptr);
1727
1728 /* Destroy http_client
1729 */
1730 void
1731 http_client_free (http_client *client);
1732
1733 /* Set on-error callback. If this callback is not NULL,
1734 * in a case of transport error it will be called instead
1735 * of the http_query callback
1736 */
1737 void
1738 http_client_onerror (http_client *client,
1739 void (*callback)(void *ptr, error err));
1740
1741 /* Cancel all pending queries, if any
1742 */
1743 void
1744 http_client_cancel (http_client *client);
1745
1746 /* Set timeout of all pending queries, if any. Timeout is in milliseconds
1747 */
1748 void
1749 http_client_timeout (http_client *client, int timeout);
1750
1751 /* Cancel all pending queries with matching address family and uintptr
1752 */
1753 void
1754 http_client_cancel_af_uintptr (http_client *client, int af, uintptr_t uintptr);
1755
1756 /* Check if client has pending queries
1757 */
1758 bool
1759 http_client_has_pending (const http_client *client);
1760
1761 /* Type http_query represents HTTP query (both request and response)
1762 */
1763 typedef struct http_query http_query;
1764
1765 /* Create new http_query
1766 *
1767 * Newly created http_query takes ownership on uri and body (if not NULL).
1768 * The method and content_type assumed to be constant strings.
1769 */
1770 http_query*
1771 http_query_new (http_client *client, http_uri *uri, const char *method,
1772 char *body, const char *content_type);
1773
1774 /* Create new http_query
1775 *
1776 * Newly created http_query takes ownership on uri and body (if not NULL).
1777 * The method and content_type assumed to be constant strings.
1778 */
1779 http_query*
1780 http_query_new_len (http_client *client, http_uri *uri, const char *method,
1781 void *body, size_t body_len, const char *content_type);
1782
1783 /* Create new http_query, relative to base URI
1784 *
1785 * Newly created http_query takes ownership on body (if not NULL).
1786 * The method and content_type assumed to be constant strings.
1787 */
1788 http_query*
1789 http_query_new_relative(http_client *client,
1790 const http_uri *base_uri, const char *path,
1791 const char *method, char *body, const char *content_type);
1792
1793 /* Set query timeout, in milliseconds. Negative timeout means 'infinite'
1794 *
1795 * This function may be called multiple times (each subsequent call overrides
1796 * a previous one)
1797 */
1798 void
1799 http_query_timeout (http_query *q, int timeout);
1800
1801 /* Set forcing port to be added to the Host header for this query.
1802 *
1803 * This function may be called multiple times (each subsequent call overrides
1804 * a previous one).
1805 */
1806 void
1807 http_query_force_port(http_query *q, bool force_port);
1808
1809 /* For this particular query override on-error callback, previously
1810 * set by http_client_onerror()
1811 *
1812 * If canllback is NULL, the completion callback, specified on a
1813 * http_query_submit() call, will be used even in a case of
1814 * transport error.
1815 */
1816 void
1817 http_query_onerror (http_query *q, void (*onerror)(void *ptr, error err));
1818
1819 /* Set on-redirect callback. It is called in a case of HTTP
1820 * redirect and may modify the supplied URI
1821 */
1822 void
1823 http_query_onredir (http_query *q,
1824 void (*onredir)(void *ptr, http_uri *uri, const http_uri *orig_uri));
1825
1826 /* Set callback that will be called, when response headers reception
1827 * is completed
1828 */
1829 void
1830 http_query_onrxhdr (http_query *q, void (*onrxhdr)(void *ptr, http_query *q));
1831
1832 /* Submit the query.
1833 *
1834 * When query is finished, callback will be called. After return from
1835 * callback, memory, owned by http_query will be invalidated
1836 */
1837 void
1838 http_query_submit (http_query *q, void (*callback)(void *ptr, http_query *q));
1839
1840 /* Get http_query timestamp. Timestamp is set when query is
1841 * submitted. And this function should not be called before
1842 * http_query_submit()
1843 */
1844 timestamp
1845 http_query_timestamp (const http_query *q);
1846
1847 /* Set uintptr_t parameter, associated with query.
1848 * Completion callback may later use http_query_get_uintptr()
1849 * to fetch this value
1850 */
1851 void
1852 http_query_set_uintptr (http_query *q, uintptr_t u);
1853
1854 /* Get uintptr_t parameter, previously set by http_query_set_uintptr()
1855 */
1856 uintptr_t
1857 http_query_get_uintptr (http_query *q);
1858
1859 /* Get query error, if any
1860 *
1861 * Both transport errors and erroneous HTTP response codes
1862 * considered as errors here
1863 */
1864 error
1865 http_query_error (const http_query *q);
1866
1867 /* Get query transport error, if any
1868 *
1869 * Only transport errors considered errors here
1870 */
1871 error
1872 http_query_transport_error (const http_query *q);
1873
1874 /* Get HTTP status code. Code not available, if query finished
1875 * with error
1876 */
1877 int
1878 http_query_status (const http_query *q);
1879
1880 /* Get HTTP status string
1881 */
1882 const char*
1883 http_query_status_string (const http_query *q);
1884
1885 /* Get query URI
1886 *
1887 * It works as http_query_orig_uri() before query is submitted
1888 * or after it is completed, and as http_query_real_uri() in
1889 * between
1890 *
1891 * This function is deprecated, use http_query_orig_uri()
1892 * or http_query_real_uri() instead
1893 */
1894 http_uri*
1895 http_query_uri (const http_query *q);
1896
1897 /* Get original URI (the same as used when http_query was created)
1898 */
1899 http_uri*
1900 http_query_orig_uri (const http_query *q);
1901
1902 /* Get real URI, that can differ from the requested URI
1903 * in a case of HTTP redirection
1904 */
1905 http_uri*
1906 http_query_real_uri (const http_query *q);
1907
1908 /* Get query method
1909 */
1910 const char*
1911 http_query_method (const http_query *q);
1912
1913 /* Set request header
1914 */
1915 void
1916 http_query_set_request_header (http_query *q, const char *name,
1917 const char *value);
1918
1919 /* Get request header
1920 */
1921 const char*
1922 http_query_get_request_header (const http_query *q, const char *name);
1923
1924 /* Get response header
1925 */
1926 const char*
1927 http_query_get_response_header (const http_query *q, const char *name);
1928
1929 /* Get request data
1930 *
1931 * You need to http_data_ref(), if you want data to remain valid
1932 * after query end of life
1933 */
1934 http_data*
1935 http_query_get_request_data (const http_query *q);
1936
1937 /* Get request data
1938 *
1939 * You need to http_data_ref(), if you want data to remain valid
1940 * after query end of life
1941 */
1942 http_data*
1943 http_query_get_response_data (const http_query *q);
1944
1945 /* Get count of parts of multipart response
1946 */
1947 int
1948 http_query_get_mp_response_count (const http_query *q);
1949
1950 /* Get data of Nth part of multipart response
1951 *
1952 * You need to http_data_ref(), if you want data to remain valid
1953 * after query end of life
1954 */
1955 http_data*
1956 http_query_get_mp_response_data (const http_query *q, int n);
1957
1958 /* Call callback for each request header
1959 */
1960 void
1961 http_query_foreach_request_header (const http_query *q,
1962 void (*callback)(const char *name, const char *value, void *ptr),
1963 void *ptr);
1964
1965 /* Call callback for each response header
1966 */
1967 void
1968 http_query_foreach_response_header (const http_query *q,
1969 void (*callback)(const char *name, const char *value, void *ptr),
1970 void *ptr);
1971
1972 /* Decode response part of the query.
1973 * This function is intended for testing purposes, not for regular use
1974 */
1975 error
1976 http_query_test_decode_response (http_query *q, const void *data, size_t size);
1977
1978 /* HTTP schemes
1979 */
1980 typedef enum {
1981 HTTP_SCHEME_UNSET = -1,
1982 HTTP_SCHEME_HTTP,
1983 HTTP_SCHEME_HTTPS,
1984 HTTP_SCHEME_UNIX
1985 } HTTP_SCHEME;
1986
1987 /* Some HTTP status codes
1988 */
1989 #ifndef NO_HTTP_STATUS
1990 enum {
1991 HTTP_STATUS_OK = 200,
1992 HTTP_STATUS_CREATED = 201,
1993 HTTP_STATUS_NOT_FOUND = 404,
1994 HTTP_STATUS_SERVICE_UNAVAILABLE = 503
1995 };
1996 #endif
1997
1998 /* Initialize HTTP client
1999 */
2000 SANE_Status
2001 http_init (void);
2002
2003 /* Initialize HTTP client
2004 */
2005 void
2006 http_cleanup (void);
2007
2008 /******************** Protocol trace ********************/
2009 /* Type trace represents an opaque handle of trace
2010 * file
2011 */
2012 typedef struct trace trace;
2013
2014 /* Initialize protocol trace. Called at backend initialization
2015 */
2016 SANE_Status
2017 trace_init (void);
2018
2019 /* Cleanup protocol trace. Called at backend unload
2020 */
2021 void
2022 trace_cleanup (void);
2023
2024 /* Open protocol trace
2025 */
2026 trace*
2027 trace_open (const char *device_name);
2028
2029 /* Ref the trace
2030 */
2031 trace*
2032 trace_ref (trace *t);
2033
2034 /* Unref the trace. When trace is not longer in use, it will be closed
2035 */
2036 void
2037 trace_unref (trace *t);
2038
2039 /* This hook is called on every http_query completion
2040 */
2041 void
2042 trace_http_query_hook (trace *t, http_query *q);
2043
2044 /* Printf to the trace log
2045 */
2046 void
2047 trace_printf (trace *t, const char *fmt, ...);
2048
2049 /* Note an error in trace log
2050 */
2051 void
2052 trace_error (trace *t, error err);
2053
2054 /* Dump message body
2055 */
2056 void
2057 trace_dump_body (trace *t, http_data *data);
2058
2059 /******************** SANE_Word/SANE_String arrays ********************/
2060 /* Create array of SANE_Word
2061 */
2062 static inline SANE_Word*
sane_word_array_new(void)2063 sane_word_array_new (void)
2064 {
2065 return mem_new(SANE_Word,1);
2066 }
2067
2068 /* Free array of SANE_Word
2069 */
2070 static inline void
sane_word_array_free(SANE_Word * a)2071 sane_word_array_free (SANE_Word *a)
2072 {
2073 mem_free(a);
2074 }
2075
2076 /* Reset array of SANE_Word
2077 */
2078 static inline void
sane_word_array_reset(SANE_Word ** a)2079 sane_word_array_reset (SANE_Word **a)
2080 {
2081 (*a)[0] = 0;
2082 }
2083
2084 /* Get length of the SANE_Word array
2085 */
2086 static inline size_t
sane_word_array_len(const SANE_Word * a)2087 sane_word_array_len (const SANE_Word *a)
2088 {
2089 return (size_t) a[0];
2090 }
2091
2092 /* Append word to array. Returns new array (old becomes invalid)
2093 */
2094 static inline SANE_Word*
sane_word_array_append(SANE_Word * a,SANE_Word w)2095 sane_word_array_append (SANE_Word *a, SANE_Word w)
2096 {
2097 size_t len = sane_word_array_len(a) + 1;
2098 a = mem_resize(a, len + 1, 0);
2099 a[0] = len;
2100 a[len] = w;
2101 return a;
2102 }
2103
2104 /* Drop array elements that outside of specified boundary
2105 */
2106 void
2107 sane_word_array_bound (SANE_Word *a, SANE_Word min, SANE_Word max);
2108
2109 /* Sort array of SANE_Word in increasing order
2110 */
2111 void
2112 sane_word_array_sort (SANE_Word *a);
2113
2114 /* Intersect two sorted arrays.
2115 */
2116 SANE_Word*
2117 sane_word_array_intersect_sorted ( const SANE_Word *a1, const SANE_Word *a2);
2118
2119 /* Create array of SANE_String
2120 */
2121 static inline SANE_String*
sane_string_array_new(void)2122 sane_string_array_new (void)
2123 {
2124 return ptr_array_new(SANE_String);
2125 }
2126
2127 /* Free array of SANE_String
2128 */
2129 static inline void
sane_string_array_free(SANE_String * a)2130 sane_string_array_free (SANE_String *a)
2131 {
2132 mem_free(a);
2133 }
2134
2135 /* Reset array of SANE_String
2136 */
2137 static inline void
sane_string_array_reset(SANE_String * a)2138 sane_string_array_reset (SANE_String *a)
2139 {
2140 ptr_array_trunc(a);
2141 }
2142
2143 /* Get length of the SANE_String array
2144 */
2145 static inline size_t
sane_string_array_len(const SANE_String * a)2146 sane_string_array_len (const SANE_String *a)
2147 {
2148 return mem_len(a);
2149 }
2150
2151 /* Append string to array Returns new array (old becomes invalid)
2152 */
2153 static inline SANE_String*
sane_string_array_append(SANE_String * a,SANE_String s)2154 sane_string_array_append(SANE_String *a, SANE_String s)
2155 {
2156 return ptr_array_append(a, s);
2157 }
2158
2159 /* Compute max string length in array of strings
2160 */
2161 size_t
2162 sane_string_array_max_strlen(const SANE_String *a);
2163
2164 /* Create array of SANE_Device
2165 */
2166 static inline const SANE_Device**
sane_device_array_new(void)2167 sane_device_array_new (void)
2168 {
2169 return ptr_array_new(const SANE_Device*);
2170 }
2171
2172 /* Free array of SANE_Device
2173 */
2174 static inline void
sane_device_array_free(const SANE_Device ** a)2175 sane_device_array_free (const SANE_Device **a)
2176 {
2177 mem_free(a);
2178 }
2179
2180 /* Get length of the SANE_Device array
2181 */
2182 static inline size_t
sane_device_array_len(const SANE_Device * const * a)2183 sane_device_array_len (const SANE_Device * const *a)
2184 {
2185 return mem_len(a);
2186 }
2187
2188 /* Append device to array. Returns new array (old becomes invalid)
2189 */
2190 static inline const SANE_Device**
sane_device_array_append(const SANE_Device ** a,SANE_Device * d)2191 sane_device_array_append(const SANE_Device **a, SANE_Device *d)
2192 {
2193 return ptr_array_append(a, d);
2194 }
2195
2196 /******************** XML utilities ********************/
2197 /* xml_ns defines XML namespace.
2198 *
2199 * For XML writer namespaces are simply added to the root
2200 * node attributes
2201 *
2202 * XML reader performs prefix substitutions
2203 *
2204 * If namespace substitution is enabled, for each note, if its
2205 * namespace matches the pattern, will be reported with name prefix
2206 * defined by substitution rule, regardless of prefix actually used
2207 * in the document
2208 *
2209 * Example:
2210 * <namespace:nodes xmlns:namespace="http://www.example.com/namespace">
2211 * <namespace:node1/>
2212 * <namespace:node2/>
2213 * <namespace:node3/>
2214 * </namespace:nodes>
2215 *
2216 * rule: {"ns", "http://www.example.com/namespace"}
2217 *
2218 * With this rule set, all nodes will be reported as if they
2219 * had the "ns" prefix, though actually their prefix in document
2220 * is different
2221 *
2222 * XML reader interprets namespace uri as a glob-style pattern,
2223 * as used by fnmatch (3) function with flags = 0
2224 */
2225 typedef struct {
2226 const char *prefix; /* Short prefix */
2227 const char *uri; /* The namespace uri (glob pattern for reader) */
2228 } xml_ns;
2229
2230 /* xml_attr represents an XML attribute.
2231 *
2232 * Attributes are supported by XML writer. Array of attributes
2233 * is terminated by the {NULL, NULL} attribute
2234 */
2235 typedef struct {
2236 const char *name; /* Attribute name */
2237 const char *value; /* Attribute value */
2238 } xml_attr;
2239
2240 /* XML reader
2241 */
2242 typedef struct xml_rd xml_rd;
2243
2244 /* Parse XML text and initialize reader to iterate
2245 * starting from the root node
2246 *
2247 * The 'ns' argument, if not NULL, points to array of substitution
2248 * rules. Last element must have NULL prefix and url
2249 *
2250 * Array of rules considered to be statically allocated
2251 * (at least, it can remain valid during reader life time)
2252 *
2253 * On success, saves newly constructed reader into
2254 * the xml parameter.
2255 */
2256 error
2257 xml_rd_begin (xml_rd **xml, const char *xml_text, size_t xml_len,
2258 const xml_ns *ns);
2259
2260 /* Finish reading, free allocated resources
2261 */
2262 void
2263 xml_rd_finish (xml_rd **xml);
2264
2265 /* Get current node depth in the tree. Root depth is 0
2266 */
2267 unsigned int
2268 xml_rd_depth (xml_rd *xml);
2269
2270 /* Check for end-of-document condition
2271 */
2272 bool
2273 xml_rd_end (xml_rd *xml);
2274
2275 /* Shift to the next node
2276 */
2277 void
2278 xml_rd_next (xml_rd *xml);
2279
2280 /* Shift to the next node, visiting the nested nodes on the way
2281 *
2282 * If depth > 0, it will not return from nested nodes
2283 * upper the specified depth
2284 */
2285 void
2286 xml_rd_deep_next (xml_rd *xml, unsigned int depth);
2287
2288 /* Enter the current node - iterate its children
2289 */
2290 void
2291 xml_rd_enter (xml_rd *xml);
2292
2293 /* Leave the current node - return to its parent
2294 */
2295 void
2296 xml_rd_leave (xml_rd *xml);
2297
2298 /* Get name of the current node.
2299 *
2300 * The returned string remains valid, until reader is cleaned up
2301 * or current node is changed (by set/next/enter/leave operations).
2302 * You don't need to free this string explicitly
2303 */
2304 const char*
2305 xml_rd_node_name (xml_rd *xml);
2306
2307 /* Get full path to the current node, '/'-separated
2308 */
2309 const char*
2310 xml_rd_node_path (xml_rd *xml);
2311
2312 /* Match name of the current node against the pattern
2313 */
2314 bool
2315 xml_rd_node_name_match (xml_rd *xml, const char *pattern);
2316
2317 /* Get value of the current node as text
2318 *
2319 * The returned string remains valid, until reader is cleaned up
2320 * or current node is changed (by set/next/enter/leave operations).
2321 * You don't need to free this string explicitly
2322 */
2323 const char*
2324 xml_rd_node_value (xml_rd *xml);
2325
2326 /* Get value of the current node as unsigned integer
2327 */
2328 error
2329 xml_rd_node_value_uint (xml_rd *xml, SANE_Word *val);
2330
2331 /* XML writer
2332 */
2333 typedef struct xml_wr xml_wr;
2334
2335 /* Begin writing XML document. Root node will be created automatically
2336 *
2337 * The ns parameter must be terminated by {NULL, NULL} structure
2338 */
2339 xml_wr*
2340 xml_wr_begin (const char *root, const xml_ns *ns);
2341
2342 /* Finish writing, generate document string.
2343 * Caller must g_free() this string after use
2344 */
2345 char*
2346 xml_wr_finish (xml_wr *xml);
2347
2348 /* Like xml_wr_finish, but returns compact representation
2349 * of XML (without indentation and new lines)
2350 */
2351 char*
2352 xml_wr_finish_compact (xml_wr *xml);
2353
2354 /* Add node with textual value
2355 */
2356 void
2357 xml_wr_add_text (xml_wr *xml, const char *name, const char *value);
2358
2359 /* Add text node with attributes
2360 */
2361 void
2362 xml_wr_add_text_attr (xml_wr *xml, const char *name, const char *value,
2363 const xml_attr *attrs);
2364
2365 /* Add node with unsigned integer value
2366 */
2367 void
2368 xml_wr_add_uint (xml_wr *xml, const char *name, unsigned int value);
2369
2370 /* Add node with unsigned integer value and attributes
2371 */
2372 void
2373 xml_wr_add_uint_attr (xml_wr *xml, const char *name, unsigned int value,
2374 const xml_attr *attrs);
2375
2376 /* Add node with boolean value
2377 */
2378 void
2379 xml_wr_add_bool (xml_wr *xml, const char *name, bool value);
2380
2381 /* Add node with boolean value and attributes
2382 */
2383 void
2384 xml_wr_add_bool_attr (xml_wr *xml, const char *name, bool value,
2385 const xml_attr *attrs);
2386
2387 /* Create node with children and enter newly added node
2388 */
2389 void
2390 xml_wr_enter (xml_wr *xml, const char *name);
2391
2392 /* xml_wr_enter with attributes
2393 */
2394 void
2395 xml_wr_enter_attr (xml_wr *xml, const char *name, const xml_attr *attrs);
2396
2397 /* Leave the current node
2398 */
2399 void
2400 xml_wr_leave (xml_wr *xml);
2401
2402 /* Format XML to file. It either succeeds, writes a formatted XML
2403 * and returns true, or fails, writes nothing to file and returns false
2404 */
2405 bool
2406 xml_format (FILE *fp, const char *xml_text, size_t xml_len);
2407
2408 /******************** Sane Options********************/
2409 /* Options numbers, for internal use
2410 */
2411 enum {
2412 OPT_NUM_OPTIONS, /* Total number of options */
2413
2414 /* Standard options group */
2415 OPT_GROUP_STANDARD,
2416 OPT_SCAN_RESOLUTION,
2417 OPT_SCAN_COLORMODE, /* I.e. color/grayscale etc */
2418 OPT_SCAN_SOURCE, /* Platem/ADF/ADF Duplex */
2419
2420 /* Geometry options group */
2421 OPT_GROUP_GEOMETRY,
2422 OPT_SCAN_TL_X,
2423 OPT_SCAN_TL_Y,
2424 OPT_SCAN_BR_X,
2425 OPT_SCAN_BR_Y,
2426
2427 /* Image enhancement group */
2428 OPT_GROUP_ENHANCEMENT,
2429 OPT_BRIGHTNESS,
2430 OPT_CONTRAST,
2431 OPT_SHADOW,
2432 OPT_HIGHLIGHT,
2433 OPT_GAMMA,
2434 OPT_NEGATIVE,
2435
2436 /* Total count of options, computed by compiler */
2437 NUM_OPTIONS
2438 };
2439
2440 /* String constants for certain SANE options values
2441 * (missed from sane/sameopt.h)
2442 */
2443 #define OPTVAL_SOURCE_PLATEN "Flatbed"
2444 #define OPTVAL_SOURCE_ADF_SIMPLEX "ADF"
2445 #define OPTVAL_SOURCE_ADF_DUPLEX "ADF Duplex"
2446
2447 /* Check if option belongs to image enhancement group
2448 */
2449 static inline bool
opt_is_enhancement(int opt)2450 opt_is_enhancement (int opt)
2451 {
2452 return OPT_BRIGHTNESS <= opt && opt <= OPT_NEGATIVE;
2453 }
2454
2455 /******************** Device Capabilities ********************/
2456 /* Source flags
2457 */
2458 enum {
2459 /* Supported Intents */
2460 DEVCAPS_SOURCE_INTENT_DOCUMENT = (1 << 3),
2461 DEVCAPS_SOURCE_INTENT_TXT_AND_GRAPH = (1 << 4),
2462 DEVCAPS_SOURCE_INTENT_PHOTO = (1 << 5),
2463 DEVCAPS_SOURCE_INTENT_PREVIEW = (1 << 6),
2464
2465 DEVCAPS_SOURCE_INTENT_ALL =
2466 DEVCAPS_SOURCE_INTENT_DOCUMENT |
2467 DEVCAPS_SOURCE_INTENT_TXT_AND_GRAPH |
2468 DEVCAPS_SOURCE_INTENT_PHOTO |
2469 DEVCAPS_SOURCE_INTENT_PREVIEW,
2470
2471 /* How resolutions are defined */
2472 DEVCAPS_SOURCE_RES_DISCRETE = (1 << 7), /* Discrete resolutions */
2473 DEVCAPS_SOURCE_RES_RANGE = (1 << 8), /* Range of resolutions */
2474
2475 DEVCAPS_SOURCE_RES_ALL =
2476 DEVCAPS_SOURCE_RES_DISCRETE |
2477 DEVCAPS_SOURCE_RES_RANGE,
2478
2479 /* Miscellaneous flags */
2480 DEVCAPS_SOURCE_HAS_SIZE = (1 << 12), /* max_width, max_height and
2481 derivatives are valid */
2482
2483 /* Protocol dialects */
2484 DEVCAPS_SOURCE_PWG_DOCFMT = (1 << 13), /* pwg:DocumentFormat */
2485 DEVCAPS_SOURCE_SCAN_DOCFMT_EXT = (1 << 14), /* scan:DocumentFormatExt */
2486 };
2487
2488 /* Supported image formats
2489 */
2490 #define DEVCAPS_FORMATS_SUPPORTED \
2491 ((1 << ID_FORMAT_JPEG) | \
2492 (1 << ID_FORMAT_PNG) | \
2493 (1 << ID_FORMAT_BMP))
2494
2495 /* Supported color modes
2496 *
2497 * Note, currently the only image format we support is JPEG
2498 * With JPEG, ID_COLORMODE_BW1 cannot be supported
2499 */
2500 #define DEVCAPS_COLORMODES_SUPPORTED \
2501 ((1 << ID_COLORMODE_COLOR) | \
2502 (1 << ID_COLORMODE_GRAYSCALE))
2503
2504 /* Source Capabilities (each device may contain multiple sources)
2505 */
2506 typedef struct {
2507 unsigned int flags; /* Source flags */
2508 unsigned int colormodes; /* Set of 1 << ID_COLORMODE */
2509 unsigned int formats; /* Set of 1 << ID_FORMAT */
2510 SANE_Word min_wid_px, max_wid_px; /* Min/max width, in pixels */
2511 SANE_Word min_hei_px, max_hei_px; /* Min/max height, in pixels */
2512 SANE_Word *resolutions; /* Discrete resolutions, in DPI */
2513 SANE_Range res_range; /* Resolutions range, in DPI */
2514 SANE_Range win_x_range_mm; /* Window x range, in mm */
2515 SANE_Range win_y_range_mm; /* Window y range, in mm */
2516 } devcaps_source;
2517
2518 /* Allocate devcaps_source
2519 */
2520 devcaps_source*
2521 devcaps_source_new (void);
2522
2523 /* Free devcaps_source
2524 */
2525 void
2526 devcaps_source_free (devcaps_source *src);
2527
2528 /* Clone a source
2529 */
2530 devcaps_source*
2531 devcaps_source_clone (const devcaps_source *src);
2532
2533 /* Merge two sources, resulting the source that contains
2534 * only capabilities, supported by two input sources
2535 *
2536 * Returns NULL, if sources cannot be merged
2537 */
2538 devcaps_source*
2539 devcaps_source_merge (const devcaps_source *s1, const devcaps_source *s2);
2540
2541 /* Device Capabilities
2542 */
2543 typedef struct {
2544 /* Fundamental values */
2545 const char *protocol; /* Protocol name */
2546 SANE_Word units; /* Size units, pixels per inch */
2547
2548 /* Image compression */
2549 bool compression_ok; /* Compression params are supported */
2550 SANE_Range compression_range; /* Compression range */
2551 SANE_Word compression_norm; /* Normal compression */
2552
2553 /* Sources */
2554 devcaps_source *src[NUM_ID_SOURCE]; /* Missed sources are NULL */
2555 } devcaps;
2556
2557 /* Initialize Device Capabilities
2558 */
2559 void
2560 devcaps_init (devcaps *caps);
2561
2562 /* Cleanup Device Capabilities
2563 */
2564 void
2565 devcaps_cleanup (devcaps *caps);
2566
2567 /* Reset Device Capabilities into initial state
2568 */
2569 void
2570 devcaps_reset (devcaps *caps);
2571
2572 /* Dump device capabilities, for debugging
2573 */
2574 void
2575 devcaps_dump (log_ctx *log, devcaps *caps);
2576
2577 /******************** Device options ********************/
2578 /* Scan options
2579 */
2580 typedef struct {
2581 devcaps caps; /* Device capabilities */
2582 SANE_Option_Descriptor desc[NUM_OPTIONS]; /* Option descriptors */
2583 ID_SOURCE src; /* Current source */
2584 ID_COLORMODE colormode_emul; /* Current "emulated" color mode*/
2585 ID_COLORMODE colormode_real; /* Current real color mode*/
2586 SANE_Word resolution; /* Current resolution */
2587 SANE_Fixed tl_x, tl_y; /* Top-left x/y */
2588 SANE_Fixed br_x, br_y; /* Bottom-right x/y */
2589 SANE_Parameters params; /* Scan parameters */
2590 SANE_String *sane_sources; /* Sources, in SANE format */
2591 SANE_String *sane_colormodes; /* Color modes in SANE format */
2592 SANE_Fixed brightness; /* -100.0 ... +100.0 */
2593 SANE_Fixed contrast; /* -100.0 ... +100.0 */
2594 SANE_Fixed shadow; /* 0.0 ... +100.0 */
2595 SANE_Fixed highlight; /* 0.0 ... +100.0 */
2596 SANE_Fixed gamma; /* Small positive value */
2597 bool negative; /* Flip black and white */
2598 } devopt;
2599
2600 /* Initialize device options
2601 */
2602 void
2603 devopt_init (devopt *opt);
2604
2605 /* Cleanup device options
2606 */
2607 void
2608 devopt_cleanup (devopt *opt);
2609
2610 /* Set default option values. Before call to this function,
2611 * devopt.caps needs to be properly filled.
2612 */
2613 void
2614 devopt_set_defaults (devopt *opt);
2615
2616 /* Set device option
2617 */
2618 SANE_Status
2619 devopt_set_option (devopt *opt, SANE_Int option, void *value, SANE_Word *info);
2620
2621 /* Get device option
2622 */
2623 SANE_Status
2624 devopt_get_option (devopt *opt, SANE_Int option, void *value);
2625
2626 /******************** ZeroConf (device discovery) ********************/
2627 /* Common logging context for device discovery
2628 */
2629 extern log_ctx *zeroconf_log;
2630
2631 /* zeroconf_device represents a single device
2632 */
2633 typedef struct zeroconf_device zeroconf_device;
2634
2635 /* zeroconf_endpoint represents a device endpoint
2636 */
2637 typedef struct zeroconf_endpoint zeroconf_endpoint;
2638 struct zeroconf_endpoint {
2639 ID_PROTO proto; /* The protocol */
2640 http_uri *uri; /* I.e, "http://192.168.1.1:8080/eSCL/" */
2641 zeroconf_endpoint *next; /* Next endpoint in the list */
2642 };
2643
2644 /* ZEROCONF_METHOD represents a method how device was discovered
2645 * The same device may be discovered using multiple methods
2646 */
2647 typedef enum {
2648 /* The following findings serve as indirect signs of
2649 * scanner presence in the network
2650 */
2651 ZEROCONF_MDNS_HINT, /* Hint finding from MDNS world */
2652
2653 /* The following findings are expected to bring actual
2654 * scanner endpoints
2655 */
2656 ZEROCONF_USCAN_TCP, /* _uscan._tcp */
2657 ZEROCONF_USCANS_TCP, /* _uscans._tcp */
2658 ZEROCONF_WSD, /* WS-Discovery */
2659
2660 NUM_ZEROCONF_METHOD
2661 } ZEROCONF_METHOD;
2662
2663 /* zeroconf_finding represents a single device discovery finding.
2664 * Multiple findings can point to the same device, and even
2665 * endpoints may duplicate between findings (say, if the same
2666 * device found using multiple network interfaces or using various
2667 * discovery methods)
2668 *
2669 * zeroconf_finding are bound to method and interface index
2670 */
2671 typedef struct {
2672 ZEROCONF_METHOD method; /* Discovery method */
2673 const char *name; /* Network-unique name, NULL for WSD */
2674 const char *model; /* Model name, may be NULL for
2675 WSDD non-scanner devices */
2676 uuid uuid; /* Device UUID */
2677 ip_addrset *addrs; /* Device addresses */
2678 int ifindex; /* Network interface index */
2679 zeroconf_endpoint *endpoints; /* List of endpoints */
2680
2681 /* The following fields are reserved for zeroconf core
2682 * and should not be used by discovery providers
2683 */
2684 zeroconf_device *device; /* Device the finding points to */
2685 ll_node list_node; /* Node in device's list of findings */
2686 } zeroconf_finding;
2687
2688 /* Publish the zeroconf_finding.
2689 *
2690 * Memory, referred by the finding, remains owned by
2691 * caller, and caller is responsible to keep this
2692 * memory valid until zeroconf_finding_withdraw()
2693 * is called
2694 *
2695 * The 'endpoinds' field may be NULL. This mechanism is
2696 * used by WS-Discovery to notify zeroconf that scanning
2697 * for particular UUID has been finished, though without
2698 * success.
2699 */
2700 void
2701 zeroconf_finding_publish (zeroconf_finding *finding);
2702
2703 /* Withdraw the finding
2704 */
2705 void
2706 zeroconf_finding_withdraw (zeroconf_finding *finding);
2707
2708 /* Notify zeroconf subsystem that initial scan
2709 * for the method is done
2710 */
2711 void
2712 zeroconf_finding_done (ZEROCONF_METHOD method);
2713
2714 /* zeroconf_devinfo represents a device information
2715 */
2716 typedef struct {
2717 const char *ident; /* Unique ident */
2718 const char *name; /* Human-friendly name */
2719 zeroconf_endpoint *endpoints; /* Device endpoints */
2720 } zeroconf_devinfo;
2721
2722 /* Initialize ZeroConf
2723 */
2724 SANE_Status
2725 zeroconf_init (void);
2726
2727 /* Cleanup ZeroConf
2728 */
2729 void
2730 zeroconf_cleanup (void);
2731
2732 /* Get list of devices, in SANE format
2733 */
2734 const SANE_Device**
2735 zeroconf_device_list_get (void);
2736
2737 /* Free list of devices, returned by zeroconf_device_list_get()
2738 */
2739 void
2740 zeroconf_device_list_free (const SANE_Device **dev_list);
2741
2742 /* Lookup device by ident (ident is reported as SANE_Device::name)
2743 * by zeroconf_device_list_get())
2744 *
2745 * Caller becomes owner of resources (name and list of endpoints),
2746 * referred by the returned zeroconf_devinfo
2747 *
2748 * Caller must free these resources, using zeroconf_devinfo_free()
2749 */
2750 zeroconf_devinfo*
2751 zeroconf_devinfo_lookup (const char *ident);
2752
2753 /* Free zeroconf_devinfo, returned by zeroconf_devinfo_lookup()
2754 */
2755 void
2756 zeroconf_devinfo_free (zeroconf_devinfo *devinfo);
2757
2758 /* Check if initial scan still in progress
2759 */
2760 bool
2761 zeroconf_init_scan (void);
2762
2763 /* Create new zeroconf_endpoint. Newly created endpoint
2764 * takes ownership of uri string
2765 */
2766 zeroconf_endpoint*
2767 zeroconf_endpoint_new (ID_PROTO proto, http_uri *uri);
2768
2769 /* Create a copy of zeroconf_endpoint list
2770 */
2771 zeroconf_endpoint*
2772 zeroconf_endpoint_list_copy (const zeroconf_endpoint *list);
2773
2774 /* Free zeroconf_endpoint list
2775 */
2776 void
2777 zeroconf_endpoint_list_free (zeroconf_endpoint *list);
2778
2779 /* Sort list of endpoints
2780 */
2781 zeroconf_endpoint*
2782 zeroconf_endpoint_list_sort (zeroconf_endpoint *list);
2783
2784 /* Sort list of endpoints and remove duplicates
2785 */
2786 zeroconf_endpoint*
2787 zeroconf_endpoint_list_sort_dedup (zeroconf_endpoint *list);
2788
2789 /* Check if endpoints list contains a non-link-local address
2790 * of the specified address family
2791 */
2792 bool
2793 zeroconf_endpoint_list_has_non_link_local_addr (int af,
2794 const zeroconf_endpoint *list);
2795
2796 /******************** MDNS Discovery ********************/
2797 /* Called by zeroconf to notify MDNS about initial scan timer expiration
2798 */
2799 void
2800 mdns_initscan_timer_expired (void);
2801
2802 /* Initialize MDNS
2803 */
2804 SANE_Status
2805 mdns_init (void);
2806
2807 /* Cleanup MDNS
2808 */
2809 void
2810 mdns_cleanup (void);
2811
2812 /******************** WS-Discovery ********************/
2813 /* Called by zeroconf to notify wsdd about initial scan timer expiration
2814 */
2815 void
2816 wsdd_initscan_timer_expired (void);
2817
2818 /* Send WD-Discovery directed probe
2819 */
2820 void
2821 wsdd_send_directed_probe (int ifindex, int af, const void *addr);
2822
2823 /* Initialize WS-Discovery
2824 */
2825 SANE_Status
2826 wsdd_init (void);
2827
2828 /* Cleanup WS-Discovery
2829 */
2830 void
2831 wsdd_cleanup (void);
2832
2833 /******************** Device Management ********************/
2834 /* Type device represents a scanner device
2835 */
2836 typedef struct device device;
2837
2838 /* Open a device
2839 */
2840 device*
2841 device_open (const char *name, SANE_Status *status);
2842
2843 /* Close the device
2844 * If log_msg is not NULL, it is written to the device log as late as possible
2845 */
2846 void
2847 device_close (device *dev, const char *log_msg);
2848
2849 /* Get device's logging context
2850 */
2851 log_ctx*
2852 device_log_ctx (device *dev);
2853
2854 /* Get option descriptor
2855 */
2856 const SANE_Option_Descriptor*
2857 device_get_option_descriptor (device *dev, SANE_Int option);
2858
2859 /* Get device option
2860 */
2861 SANE_Status
2862 device_get_option (device *dev, SANE_Int option, void *value);
2863
2864 /* Set device option
2865 */
2866 SANE_Status
2867 device_set_option (device *dev, SANE_Int option, void *value, SANE_Word *info);
2868
2869 /* Get current scan parameters
2870 */
2871 SANE_Status
2872 device_get_parameters (device *dev, SANE_Parameters *params);
2873
2874 SANE_Status
2875 device_start (device *dev);
2876
2877 /* Cancel scanning operation
2878 */
2879 void
2880 device_cancel (device *dev);
2881
2882 /* Set I/O mode
2883 */
2884 SANE_Status
2885 device_set_io_mode (device *dev, SANE_Bool non_blocking);
2886
2887 /* Get select file descriptor
2888 */
2889 SANE_Status
2890 device_get_select_fd (device *dev, SANE_Int *fd);
2891
2892 /* Read scanned image
2893 */
2894 SANE_Status
2895 device_read (device *dev, SANE_Byte *data, SANE_Int max_len, SANE_Int *len);
2896
2897 /* Initialize device management
2898 */
2899 SANE_Status
2900 device_management_init (void);
2901
2902 /* Cleanup device management
2903 */
2904 void
2905 device_management_cleanup (void);
2906
2907 /******************** Image filters ********************/
2908 /* Type filter represents image filter
2909 */
2910 typedef struct filter filter;
2911 struct filter {
2912 filter *next; /* Next filter in a chain */
2913 void (*dump) (filter *f, /* Dump filter to the log */
2914 log_ctx *log);
2915 void (*free) (filter *f); /* Free the filter */
2916 void (*apply) (filter *f, /* Apply filter to the line of image */
2917 uint8_t *line, size_t size);
2918 };
2919
2920 /* Free chain of filters
2921 */
2922 void
2923 filter_chain_free (filter *chain);
2924
2925 /* Push translation table based filter, that handles the
2926 * following options:
2927 * - brightness
2928 * - contrast
2929 * - negative
2930 *
2931 * Returns updated chain
2932 */
2933 filter*
2934 filter_chain_push_xlat (filter *old_chain, const devopt *opt);
2935
2936 /* Dump filter chain to the log
2937 */
2938 void
2939 filter_chain_dump (filter *chain, log_ctx *log);
2940
2941 /* Apply filter chain to the image line
2942 */
2943 void
2944 filter_chain_apply (filter *chain, uint8_t *line, size_t size);
2945
2946 /******************** Scan Protocol handling ********************/
2947 /* PROTO_OP represents operation
2948 */
2949 typedef enum {
2950 PROTO_OP_NONE, /* No operation */
2951 PROTO_OP_PRECHECK,/* Pre-scan check */
2952 PROTO_OP_SCAN, /* New scan */
2953 PROTO_OP_LOAD, /* Load image */
2954 PROTO_OP_CHECK, /* Check device status */
2955 PROTO_OP_CLEANUP, /* Cleanup after scan */
2956 PROTO_OP_FINISH /* Finish scanning */
2957 } PROTO_OP;
2958
2959 /* Get PROTO_OP name, for logging
2960 */
2961 const char*
2962 proto_op_name (PROTO_OP op);
2963
2964 /* proto_scan_params represents scan parameters
2965 */
2966 typedef struct {
2967 int x_off, y_off; /* Scan area X/Y offset */
2968 int wid, hei; /* Scan area width and height */
2969 int x_res, y_res; /* X/Y resolution */
2970 ID_SOURCE src; /* Desired source */
2971 ID_COLORMODE colormode; /* Desired color mode */
2972 ID_FORMAT format; /* Image format */
2973 } proto_scan_params;
2974
2975 /* proto_ctx represents request context
2976 */
2977 typedef struct {
2978 /* Common context */
2979 log_ctx *log; /* Logging context */
2980 struct proto_handler *proto; /* Link to proto_handler */
2981 const devcaps *devcaps; /* Device capabilities */
2982 PROTO_OP op; /* Current operation */
2983 http_client *http; /* HTTP client for sending requests */
2984 http_uri *base_uri; /* HTTP base URI for protocol */
2985 http_uri *base_uri_nozone;/* base_uri without IPv6 zone */
2986 proto_scan_params params; /* Scan parameters */
2987 const char *location; /* Image location */
2988 unsigned int images_received; /* Total count of received images */
2989
2990 /* Extra context for xxx_decode callbacks */
2991 const http_query *query; /* Passed to xxx_decode callbacks */
2992
2993 /* Extra context for status_decode callback */
2994 PROTO_OP failed_op; /* Failed operation */
2995 int failed_http_status; /* Its HTTP status */
2996 int failed_attempt; /* Retry count, 0-based */
2997 } proto_ctx;
2998
2999 /* proto_result represents decoded query results
3000 */
3001 typedef struct {
3002 PROTO_OP next; /* Next operation */
3003 int delay; /* In milliseconds */
3004 SANE_Status status; /* Job status */
3005 error err; /* Error string, may be NULL */
3006 union {
3007 const char *location; /* Image location, protocol-specific */
3008 http_data *image; /* Image buffer */
3009 } data;
3010 } proto_result;
3011
3012 /* proto represents scan protocol implementation
3013 */
3014 typedef struct proto_handler proto_handler;
3015 struct proto_handler {
3016 const char *name; /* Protocol name (i.e., "eSCL", "WSD", "IPP") */
3017
3018 /* Free protocol handler
3019 */
3020 void (*free) (proto_handler *proto);
3021
3022 /* Query and decode device capabilities
3023 */
3024 http_query* (*devcaps_query) (const proto_ctx *ctx);
3025 error (*devcaps_decode) (const proto_ctx *ctx, devcaps *caps);
3026
3027 /* Create pre-scan check query and decode result
3028 * These callback are optional, set to NULL, if
3029 * they are not implemented by the protocol
3030 * handler
3031 */
3032 http_query* (*precheck_query) (const proto_ctx *ctx);
3033 proto_result (*precheck_decode) (const proto_ctx *ctx);
3034
3035 /* Initiate scanning and decode result.
3036 * On success, scan_decode must set ctx->data.location
3037 */
3038 http_query* (*scan_query) (const proto_ctx *ctx);
3039 proto_result (*scan_decode) (const proto_ctx *ctx);
3040
3041 /* Initiate image downloading and decode result.
3042 * On success, load_decode must set ctx->data.image
3043 */
3044 http_query* (*load_query) (const proto_ctx *ctx);
3045 proto_result (*load_decode) (const proto_ctx *ctx);
3046
3047 /* Request device status and decode result
3048 */
3049 http_query* (*status_query) (const proto_ctx *ctx);
3050 proto_result (*status_decode) (const proto_ctx *ctx);
3051
3052 /* Cleanup after scan
3053 */
3054 http_query* (*cleanup_query) (const proto_ctx *ctx);
3055
3056 /* Cancel scan in progress
3057 */
3058 http_query* (*cancel_query) (const proto_ctx *ctx);
3059 };
3060
3061 /* proto_handler_escl_new creates new eSCL protocol handler
3062 */
3063 proto_handler*
3064 proto_handler_escl_new (void);
3065
3066 /* proto_handler_wsd_new creates new WSD protocol handler
3067 */
3068 proto_handler*
3069 proto_handler_wsd_new (void);
3070
3071 /* proto_handler_new creates new protocol handler by protocol ID
3072 */
3073 static inline proto_handler*
proto_handler_new(ID_PROTO proto)3074 proto_handler_new (ID_PROTO proto)
3075 {
3076 switch (proto) {
3077 case ID_PROTO_ESCL:
3078 return proto_handler_escl_new();
3079 case ID_PROTO_WSD:
3080 return proto_handler_wsd_new();
3081 default:
3082 return NULL;
3083 }
3084 }
3085
3086 /******************** Image decoding ********************/
3087 /* The window withing the image
3088 *
3089 * Note, all sizes and coordinates are in pixels
3090 */
3091 typedef struct {
3092 int x_off, y_off; /* Top-left corner offset */
3093 int wid, hei; /* Image width and height */
3094 } image_window;
3095
3096 /* Image decoder, with virtual methods
3097 */
3098 typedef struct image_decoder image_decoder;
3099 struct image_decoder {
3100 const char *content_type;
3101 void (*free) (image_decoder *decoder);
3102 error (*begin) (image_decoder *decoder, const void *data, size_t size);
3103 void (*reset) (image_decoder *decoder);
3104 int (*get_bytes_per_pixel) (image_decoder *decoder);
3105 void (*get_params) (image_decoder *decoder, SANE_Parameters *params);
3106 error (*set_window) (image_decoder *decoder, image_window *win);
3107 error (*read_line) (image_decoder *decoder, void *buffer);
3108 };
3109
3110 /* Create JPEG image decoder
3111 */
3112 image_decoder*
3113 image_decoder_jpeg_new (void);
3114
3115 /* Create PNG image decoder
3116 */
3117 image_decoder*
3118 image_decoder_png_new (void);
3119
3120 /* Create BMP image decoder
3121 */
3122 image_decoder*
3123 image_decoder_bmp_new (void);
3124
3125 /* Free image decoder
3126 */
3127 static inline void
image_decoder_free(image_decoder * decoder)3128 image_decoder_free (image_decoder *decoder)
3129 {
3130 decoder->free(decoder);
3131 }
3132
3133 /* Get content type
3134 */
3135 static inline const char*
image_content_type(image_decoder * decoder)3136 image_content_type (image_decoder *decoder)
3137 {
3138 return decoder->content_type;
3139 }
3140
3141 /* Begin image decoding. Decoder may assume that provided data
3142 * buffer remains valid during a whole decoding cycle
3143 */
3144 static inline error
image_decoder_begin(image_decoder * decoder,const void * data,size_t size)3145 image_decoder_begin (image_decoder *decoder, const void *data, size_t size)
3146 {
3147 return decoder->begin(decoder, data, size);
3148 }
3149
3150 /* Reset image decoder after use. After reset, decoding of the
3151 * another image can be started
3152 */
3153 static inline void
image_decoder_reset(image_decoder * decoder)3154 image_decoder_reset (image_decoder *decoder)
3155 {
3156 decoder->reset(decoder);
3157 }
3158
3159 /* Get bytes count per pixel
3160 */
3161 static inline int
image_decoder_get_bytes_per_pixel(image_decoder * decoder)3162 image_decoder_get_bytes_per_pixel (image_decoder *decoder)
3163 {
3164 return decoder->get_bytes_per_pixel(decoder);
3165 }
3166
3167 /* Get image parameters. Can be called at any time between
3168 * image_decoder_begin() and image_decoder_reset()
3169 *
3170 * Decoder must return an actual image parameters, regardless
3171 * of clipping window set by image_decoder_set_window()
3172 */
3173 static inline void
image_decoder_get_params(image_decoder * decoder,SANE_Parameters * params)3174 image_decoder_get_params (image_decoder *decoder, SANE_Parameters *params)
3175 {
3176 decoder->get_params(decoder, params);
3177 }
3178
3179 /* Set window within the image. Only part of image that fits the
3180 * window needs to be decoded. Decoder may assume that window is
3181 * always within the actual image boundaries
3182 *
3183 * Note, if decoder cannot handle exact window boundaries, it
3184 * it must update window to keep actual values
3185 *
3186 * In particular, if decoder doesn't implement image clipping
3187 * at all, it is safe that decoder will simply set window boundaries
3188 * to contain an entire image
3189 */
3190 static inline error
image_decoder_set_window(image_decoder * decoder,image_window * win)3191 image_decoder_set_window (image_decoder *decoder, image_window *win)
3192 {
3193 return decoder->set_window(decoder, win);
3194 }
3195
3196 /* Read next line of image. Decoder may safely assume the provided
3197 * buffer is big enough to keep the entire line
3198 */
3199 static inline error
image_decoder_read_line(image_decoder * decoder,void * buffer)3200 image_decoder_read_line (image_decoder *decoder, void *buffer)
3201 {
3202 return decoder->read_line(decoder, buffer);
3203 }
3204
3205 /******************** Mathematical Functions ********************/
3206 /* Find greatest common divisor of two positive integers
3207 */
3208 SANE_Word
3209 math_gcd (SANE_Word x, SANE_Word y);
3210
3211 /* Find least common multiple of two positive integers
3212 */
3213 SANE_Word
3214 math_lcm (SANE_Word x, SANE_Word y);
3215
3216 /* Find min of two words
3217 */
3218 static inline SANE_Word
math_min(SANE_Word a,SANE_Word b)3219 math_min (SANE_Word a, SANE_Word b)
3220 {
3221 return a < b ? a : b;
3222 }
3223
3224 /* Find max of two words
3225 */
3226 static inline SANE_Word
math_max(SANE_Word a,SANE_Word b)3227 math_max (SANE_Word a, SANE_Word b)
3228 {
3229 return a > b ? a : b;
3230 }
3231
3232 /* Bound integer within range
3233 */
3234 static inline SANE_Word
math_bound(SANE_Word x,SANE_Word min,SANE_Word max)3235 math_bound (SANE_Word x, SANE_Word min, SANE_Word max)
3236 {
3237 if (x < min) {
3238 return min;
3239 } else if (x > max) {
3240 return max;
3241 } else {
3242 return x;
3243 }
3244 }
3245
3246 /* Bound double within range
3247 */
3248 static inline double
math_bound_double(double x,double min,double max)3249 math_bound_double (double x, double min, double max)
3250 {
3251 if (x < min) {
3252 return min;
3253 } else if (x > max) {
3254 return max;
3255 } else {
3256 return x;
3257 }
3258 }
3259
3260 /* Compute x * mul / div, taking in account rounding
3261 * and integer overflow
3262 */
3263 static inline SANE_Word
math_muldiv(SANE_Word x,SANE_Word mul,SANE_Word div)3264 math_muldiv (SANE_Word x, SANE_Word mul, SANE_Word div)
3265 {
3266 int64_t tmp;
3267
3268 tmp = (int64_t) x * (int64_t) mul;
3269 tmp += div / 2;
3270 tmp /= div;
3271
3272 return (SANE_Word) tmp;
3273 }
3274
3275 /* Merge two ranges, if possible
3276 */
3277 bool
3278 math_range_merge (SANE_Range *out, const SANE_Range *r1, const SANE_Range *r2);
3279
3280 /* Choose nearest integer in range
3281 */
3282 SANE_Word
3283 math_range_fit (const SANE_Range *r, SANE_Word i);
3284
3285 /* Convert pixels to millimeters, using given resolution
3286 */
3287 static inline SANE_Fixed
math_px2mm_res(SANE_Word px,SANE_Word res)3288 math_px2mm_res (SANE_Word px, SANE_Word res)
3289 {
3290 return SANE_FIX((double) px * 25.4 / res);
3291 }
3292
3293 /* Convert millimeters to pixels, using given resolution
3294 */
3295 static inline SANE_Word
math_mm2px_res(SANE_Fixed mm,SANE_Word res)3296 math_mm2px_res (SANE_Fixed mm, SANE_Word res)
3297 {
3298 return (SANE_Word) roundl(SANE_UNFIX(mm) * res / 25.4);
3299 }
3300
3301 /* Format millimeters, for printing
3302 */
3303 char*
3304 math_fmt_mm (SANE_Word mm, char buf[]);
3305
3306 /* Genrate random 32-bit integer
3307 */
3308 uint32_t
3309 math_rand_u32 (void);
3310
3311 /* Generate random integer in range [0...max], inclusively
3312 */
3313 uint32_t
3314 math_rand_max (uint32_t max);
3315
3316 /* Generate random integer in range [min...max], inclusively
3317 */
3318 uint32_t
3319 math_rand_range (uint32_t min, uint32_t max);
3320
3321 /* Count nonzero bits in 32-bit integer
3322 */
3323 static inline unsigned int
math_popcount(unsigned int n)3324 math_popcount (unsigned int n)
3325 {
3326 unsigned int count = (n & 0x55555555) + ((n >> 1) & 0x55555555);
3327 count = (count & 0x33333333) + ((count >> 2) & 0x33333333);
3328 count = (count & 0x0F0F0F0F) + ((count >> 4) & 0x0F0F0F0F);
3329 count = (count & 0x00FF00FF) + ((count >> 8) & 0x00FF00FF);
3330 return (count & 0x0000FFFF) + ((count >> 16) & 0x0000FFFF);
3331 }
3332
3333 /******************** Logging ********************/
3334 /* Initialize logging
3335 *
3336 * No log messages should be generated before this call
3337 */
3338 void
3339 log_init (void);
3340
3341 /* Cleanup logging
3342 *
3343 * No log messages should be generated after this call
3344 */
3345 void
3346 log_cleanup (void);
3347
3348 /* Notify logger that configuration is loaded and
3349 * logger can configure itself
3350 *
3351 * This is safe to generate log messages before log_configure()
3352 * is called. These messages will be buffered, and after
3353 * logger is configured, either written or abandoned, depending
3354 * on configuration
3355 */
3356 void
3357 log_configure (void);
3358
3359 /* log_ctx_new creates new logging context
3360 * If parent != NULL, new logging context will have its own prefix,
3361 * but trace file will be inherited from parent
3362 */
3363 log_ctx*
3364 log_ctx_new (const char *name, log_ctx *parent);
3365
3366 /* log_ctx_free destroys logging context
3367 */
3368 void
3369 log_ctx_free (log_ctx *log);
3370
3371 /* Get protocol trace associated with logging context
3372 */
3373 trace*
3374 log_ctx_trace (log_ctx *log);
3375
3376 /* Write a debug message.
3377 */
3378 void
3379 log_debug (log_ctx *log, const char *fmt, ...);
3380
3381 /* Write a protocol trace message
3382 */
3383 void
3384 log_trace (log_ctx *log, const char *fmt, ...);
3385
3386 /* Write a block of data into protocol trace
3387 */
3388 void
3389 log_trace_data (log_ctx *log, const char *content_type,
3390 const void *bytes, size_t size);
3391
3392 /* Write an error message and terminate a program.
3393 */
3394 void
3395 log_panic (log_ctx *log, const char *fmt, ...);
3396
3397 /* Panic if assertion fails
3398 */
3399 #define log_assert(log,expr) \
3400 do { \
3401 if (!(expr)) { \
3402 log_panic(log,"file %s: line %d (%s): assertion failed: (%s)",\
3403 __FILE__, __LINE__, __PRETTY_FUNCTION__, #expr); \
3404 __builtin_unreachable(); \
3405 } \
3406 } while (0)
3407
3408 /* Panic if this code is reached
3409 */
3410 #define log_internal_error(log) \
3411 do { \
3412 log_panic(log,"file %s: line %d (%s): internal error", \
3413 __FILE__, __LINE__, __PRETTY_FUNCTION__); \
3414 __builtin_unreachable(); \
3415 } while (0)
3416
3417 /******************** Initialization/Cleanup ********************/
3418 /* AIRSCAN_INIT_FLAGS represents airscan_init() flags
3419 */
3420 typedef enum {
3421 AIRSCAN_INIT_NO_CONF = (1 << 0), // Don't load configuration
3422 AIRSCAN_INIT_NO_THREAD = (1 << 1) // Don't start worker thread
3423 } AIRSCAN_INIT_FLAGS;
3424
3425 /* Initialize airscan.
3426 * If log_msg is not NULL, it is written to the log early
3427 */
3428 SANE_Status
3429 airscan_init (AIRSCAN_INIT_FLAGS flags, const char *log_msg);
3430
3431 /* Cleanup airscan
3432 * If log_msg is not NULL, it is written to the log as late as possible
3433 */
3434 void
3435 airscan_cleanup (const char *log_msg);
3436
3437 #ifdef __cplusplus
3438 };
3439 #endif
3440
3441 #endif
3442 /* vim:ts=8:sw=4:et
3443 */
3444