2 #include "../lib/include/sblist.h"
3 #include "../lib/include/strlib.h"
6 static volatile int server_done
= 0;
15 static void dump_json_str(int fd
, const char *key
, const char *val
) {
16 dprintf(fd
, "\"%s\" : \"%s\", ", key
, val
);
18 static void dump_json_int(int fd
, const char *key
, int val
) {
19 dprintf(fd
, "\"%s\" : %d, ", key
, val
);
22 static void dump_wlan_json(int fd
, size_t wlanid
) {
23 struct wlaninfo wtmp
, *w
= &wtmp
;
26 assert(sizeof buf
>= WPS_MAX_STR_LEN
*4);
27 assert(sizeof buf
>= sizeof(wlans
[0].essid
)*4);
29 dump_json_str(fd
, "bssid", mac2str(w
->mac
, buf
));
30 dump_json_str(fd
, "essid", sanitize_string(w
->essid
, buf
));
31 dump_json_int(fd
, "channel", w
->channel
);
32 dump_json_int(fd
, "rssi", w
->last_rssi
);
33 dump_json_str(fd
, "enc", enctype_str(w
->enctype
));
34 dump_json_str(fd
, "uptime", format_timestamp(w
->timestamp
, buf
));
36 if(!w
->wps
) goto wps_done
;
38 //if(w->wps->vendor[0]) drintf(fd, "\"vendor_oui\" : \"%02X%02X%02X\", ", vendor[0], vendor[1], vendor[2]);
39 if(w
->wps
->version
) dump_json_int(fd
, "wps_version", w
->wps
->version
);
40 if(w
->wps
->state
) dump_json_int(fd
, "wps_state", w
->wps
->state
);
41 if(w
->wps
->locked
) dump_json_int(fd
, "wps_locked", w
->wps
->locked
);
43 if(w
->wps
->manufacturer
[0]) dump_json_str(fd
, "wps_manufacturer", sanitize_string(w
->wps
->manufacturer
, buf
));
44 if(w
->wps
->model_name
[0]) dump_json_str(fd
, "wps_model_name", sanitize_string(w
->wps
->model_name
, buf
));
45 if(w
->wps
->model_number
[0]) dump_json_str(fd
, "wps_model_number", sanitize_string(w
->wps
->model_number
, buf
));
46 if(w
->wps
->device_name
[0]) dump_json_str(fd
, "wps_device_name", sanitize_string(w
->wps
->device_name
, buf
));
47 if(w
->wps
->ssid
[0]) dump_json_str(fd
, "wps_ssid", sanitize_string(w
->wps
->ssid
, buf
));
48 if(w
->wps
->serial
[0]) dump_json_str(fd
, "wps_serial", sanitize_string(w
->wps
->serial
, buf
));
49 if(w
->wps
->os_version
[0]) dump_json_str(fd
, "wps_os_version", sanitize_string(w
->wps
->os_version
, buf
));
50 if(w
->wps
->uuid
[0]) dump_json_str(fd
, "wps_uuid", sanitize_string(w
->wps
->uuid
, buf
));
51 if(w
->wps
->selected_registrar
[0]) dump_json_str(fd
, "wps_selected_registrar", sanitize_string(w
->wps
->selected_registrar
, buf
));
52 if(w
->wps
->response_type
[0]) dump_json_str(fd
, "wps_response_type", sanitize_string(w
->wps
->response_type
, buf
));
53 if(w
->wps
->primary_device_type
[0]) dump_json_str(fd
, "wps_primary_device_type", sanitize_string(w
->wps
->primary_device_type
, buf
));
54 if(w
->wps
->config_methods
[0]) dump_json_str(fd
, "wps_config_methods", sanitize_string(w
->wps
->config_methods
, buf
));
55 if(w
->wps
->rf_bands
[0]) dump_json_str(fd
, "wps_rf_bands", sanitize_string(w
->wps
->rf_bands
, buf
));
58 dprintf(fd
, "\"dummy\": 0}\n");
61 static void* clientthread(void *data
) {
62 struct thread
*t
= data
;
67 n
= recv(t
->client
.fd
, buf
, sizeof buf
, 0);
69 if(!strcmp(buf
, "LIST\n")) {
71 l
= DYNA_COUNT(wlans
);
75 long long ls
= wlans
[i
].last_seen
;
77 if(ls
> t
->last_update
)
78 dump_wlan_json(t
->client
.fd
, i
);
80 t
->last_update
= getutime64();
81 dprintf(t
->client
.fd
, "END\n");
82 } else if (!strcmp(buf
, "QUIT\n")) {
84 } else if(!strcmp(buf
, "UNSELECT\n")) {
86 } else if((!strncmp(buf
, "SELECT ", 7))
87 && strlen(buf
) == 7 + 6*2 + 5 + 1
88 && buf
[7 + 6*2 + 5] == '\n'
90 unsigned char mac
[6], *m
= mac
;
95 *m
= *m
<< 4 | hexval(p
);
101 l
= DYNA_COUNT(wlans
);
103 if(!memcmp(wlans
[i
].mac
, mac
, 6)) {
118 static void collect(sblist
*threads
) {
120 for(i
=0;i
<sblist_getsize(threads
);) {
121 struct thread
* thread
= *((struct thread
**)sblist_get(threads
, i
));
123 pthread_join(thread
->pt
, 0);
124 sblist_delete(threads
, i
);
131 struct netgui_config
{
133 const char *listenaddr
;
137 static void* netgui_thread(void *args
) {
138 struct netgui_config
*cfg
= args
;
139 signal(SIGPIPE
, SIG_IGN
);
141 sblist
*threads
= sblist_new(sizeof (struct thread
*), 8);
143 if(server_setup(&s
, cfg
->listenaddr
, cfg
->port
)) {
144 perror("server_setup");
147 while(!server_done
) {
150 struct thread
*curr
= malloc(sizeof (struct thread
));
153 if(server_waitclient(&s
, &c
)) continue;
155 if(!sblist_add(threads
, &curr
)) {
156 close(curr
->client
.fd
);
159 //dolog("rejecting connection due to OOM\n");
160 usleep(16); /* prevent 100% CPU usage in OOM situation */
163 pthread_attr_t
*a
= 0, attr
;
164 if(pthread_attr_init(&attr
) == 0) {
166 pthread_attr_setstacksize(a
, 64*1024);
168 if(pthread_create(&curr
->pt
, a
, clientthread
, curr
) != 0) {
169 //dolog("pthread_create failed. OOM?\n");
171 if(a
) pthread_attr_destroy(&attr
);
174 for(i
=0;i
<sblist_getsize(threads
);i
++) {
175 struct thread
* thread
=
176 *((struct thread
**)sblist_get(threads
, i
));
177 close(thread
->client
.fd
);
184 void netgui_start(struct netgui_config
*cfg
, const char *listenaddr
, int port
) {
186 cfg
->listenaddr
= listenaddr
,
187 pthread_create(&cfg
->thr
, 0, netgui_thread
, cfg
);
190 void netgui_stop(struct netgui_config
*cfg
) {
193 /* connect to the listener so it returns from server_waitclient() */
194 int fd
= socket(AF_INET
, SOCK_STREAM
| SOCK_CLOEXEC
, 0);
195 if(fd
== -1) goto skip
;
197 struct addrinfo
*ainfo
= 0;
198 const char *dst
= "127.0.0.1";
199 if(strcmp(cfg
->listenaddr
, "0.0.0.0"))
200 dst
= cfg
->listenaddr
;
201 if(resolve(dst
, cfg
->port
, &ainfo
)) goto skip
;
203 connect(fd
, ainfo
->ai_addr
, ainfo
->ai_addrlen
);
207 pthread_join(cfg
->thr
, 0);