1 /*
2 * Copyright 2015-2016, Björn Ståhl
3 * License: 3-Clause BSD, see COPYING file in arcan source repository.
4 * Reference: http://arcan-fe.com
5 */
6
7 #include <stdio.h>
8 #include <stdint.h>
9 #include <stdbool.h>
10 #include <stdlib.h>
11 #include <sys/mman.h>
12
13 #define FRAMESERVER_PRIVATE
14 #define LUA_PRIVATE
15 #define A3D_PRIVATE
16
17 #include "arcan_shmif.h"
18 #include "arcan_math.h"
19 #include "arcan_audio.h"
20 #include "arcan_general.h"
21 #include "arcan_event.h"
22
23 #include PLATFORM_HEADER
24 #include "arcan_video.h"
25 #include "arcan_frameserver.h"
26 #include "arcan_lua.h"
27 #include "arcan_3dbase.h"
28 #include "arcan_ffunc_lut.h"
29 #include "arcan_vr.h"
30
31 #ifdef ARCAN_LWA
32 extern enum arcan_ffunc_rv arcan_lwa_ffunc FFUNC_HEAD;
33 #endif
34
35 /*
36 * will be allocated / initialized once
37 */
38 static arcan_vfunc_cb* f_lut;
39 extern int system_page_size;
40
41 static enum arcan_ffunc_rv fatal_ffunc FFUNC_HEAD
42 {
43 /* avoid the possible infinite recursion in delete(broken ffunc)->
44 * fatal->delete->... */
45 static bool in_fatal;
46 if (in_fatal)
47 return FRV_NOFRAME;
48
49 abort();
50 in_fatal = true;
51 arcan_fatal("ffunc_lut(), invalid index used in ffunc CB - \n"
52 "\tinvestigate malicious activity or data corruption\n");
53
54 return FRV_NOFRAME;
55 }
56
57 static enum arcan_ffunc_rv null_ffunc FFUNC_HEAD
58 {
59 return FRV_NOFRAME;
60 }
61
arcan_ffunc_initlut()62 void arcan_ffunc_initlut()
63 {
64 /* recovery scripts might force this to be called multiple times */
65 if (f_lut){
66 munmap(f_lut, system_page_size);
67 f_lut= NULL;
68 }
69
70 f_lut = mmap(NULL, system_page_size,
71 PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
72
73 if (!f_lut)
74 arcan_fatal("ffunc_lut() investigate memory issues");
75
76 for (size_t i = 0; i < system_page_size / sizeof(arcan_vfunc_cb*); i++)
77 f_lut[i] = fatal_ffunc;
78
79 f_lut[FFUNC_NULL] = null_ffunc;
80
81 f_lut[FFUNC_AVFEED] = arcan_frameserver_avfeedframe;
82 f_lut[FFUNC_FEEDCOPY] = arcan_frameserver_feedcopy;
83 f_lut[FFUNC_NULLFRAME] = arcan_frameserver_emptyframe;
84 f_lut[FFUNC_VFRAME] = arcan_frameserver_vdirect;
85 f_lut[FFUNC_NULLFEED] = arcan_frameserver_nullfeed;
86 f_lut[FFUNC_LUA_PROC] = arcan_lua_proctarget;
87 f_lut[FFUNC_3DOBJ] = arcan_ffunc_3dobj;
88 f_lut[FFUNC_SOCKVER] = arcan_frameserver_verifyffunc;
89 f_lut[FFUNC_SOCKPOLL] = arcan_frameserver_pollffunc;
90 f_lut[FFUNC_VR] = arcan_vr_ffunc;
91
92 #ifdef ARCAN_LWA
93 f_lut[FFUNC_LWA] = arcan_lwa_ffunc;
94 #else
95 f_lut[FFUNC_LWA] = fatal_ffunc;
96 #endif
97
98 mprotect(f_lut, system_page_size, PROT_READ);
99 }
100
arcan_ffunc_register(arcan_vfunc_cb cb)101 int arcan_ffunc_register(arcan_vfunc_cb cb)
102 {
103 int found = -1;
104
105 /* sweep the adressable range, look for one entry that is not 0 or
106 * LWA and that references the fatal ffunc */
107 for (size_t i = 1; i < 256; i++){
108 if (f_lut[i] == fatal_ffunc && i != FFUNC_LWA){
109 found = i;
110 break;
111 }
112 }
113
114 /* out of space */
115 if (found == -1)
116 return -1;
117
118 /* protect against multiple register calls on the same function */
119 for (size_t i = 0; i < 256; i++){
120 if (f_lut[i] == cb)
121 return i;
122 }
123
124 /* register (need to unprotect) */
125 mprotect(f_lut, system_page_size, PROT_READ | PROT_WRITE);
126 f_lut[found] = cb;
127 mprotect(f_lut, system_page_size, PROT_READ);
128
129 return found;
130 }
131
arcan_ffunc_lookup(ffunc_ind ind)132 arcan_vfunc_cb arcan_ffunc_lookup(ffunc_ind ind)
133 {
134 return f_lut[ind];
135 }
136