BRL-CAD
fbserv_obj.c
Go to the documentation of this file.
1 /* F B S E R V _ O B J . C
2  * BRL-CAD
3  *
4  * Copyright (c) 2004-2014 United States Government as represented by
5  * the U.S. Army Research Laboratory.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * version 2.1 as published by the Free Software Foundation.
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this file; see the file named COPYING for more
18  * information.
19  */
20 /** @addtogroup fb */
21 /** @{ */
22 /** @file fbserv_obj.c
23  *
24  * A framebuffer server object contains the attributes and
25  * methods for implementing an fbserv. This code was developed
26  * in large part by modifying the stand-alone version of fbserv.
27  *
28  */
29 /** @} */
30 
31 #include "common.h"
32 
33 #include <stdlib.h>
34 #include <string.h>
35 #include <ctype.h>
36 
37 #ifdef HAVE_WINSOCK_H
38 # include <process.h>
39 # include <winsock.h>
40 #else
41 # include <sys/socket.h>
42 # include <netinet/in.h> /* For htonl(), etc. */
43 #endif
44 #include <tcl.h>
45 
46 #include "raytrace.h"
47 #include "dm.h"
48 
49 #include "fbmsg.h"
50 #include "fbserv_obj.h"
51 #include "fb_private.h"
52 
53 
54 static fb *curr_fbp; /* current framebuffer pointer */
55 
56 
57 /*
58  * Communication error. An error occurred on the PKG link.
59  */
60 HIDDEN void
61 comm_error(const char *str)
62 {
63  bu_log("%s", str);
64 }
65 
66 
67 HIDDEN void
68 drop_client(struct fbserv_obj *fbsp, int sub)
69 {
70  if (fbsp->fbs_clients[sub].fbsc_pkg != PKC_NULL) {
71  pkg_close(fbsp->fbs_clients[sub].fbsc_pkg);
72  fbsp->fbs_clients[sub].fbsc_pkg = PKC_NULL;
73  }
74 
75  if (fbsp->fbs_clients[sub].fbsc_fd != 0) {
76 #if defined(_WIN32) && !defined(__CYGWIN__)
77  Tcl_DeleteChannelHandler(fbsp->fbs_clients[sub].fbsc_chan, fbsp->fbs_clients[sub].fbsc_handler, (ClientData)fbsp->fbs_clients[sub].fbsc_fd);
78 
79  Tcl_Close(fbsp->fbs_interp, fbsp->fbs_clients[sub].fbsc_chan);
80  fbsp->fbs_clients[sub].fbsc_chan = NULL;
81 #else
82  Tcl_DeleteFileHandler(fbsp->fbs_clients[sub].fbsc_fd);
83 #endif
84 
85  fbsp->fbs_clients[sub].fbsc_fd = 0;
86  }
87 }
88 
89 
90 /*
91  * Process arrivals from existing clients.
92  */
93 HIDDEN void
94 existing_client_handler(ClientData clientData, int UNUSED(mask))
95 {
96  register int i;
97  struct fbserv_client *fbscp = (struct fbserv_client *)clientData;
98  struct fbserv_obj *fbsp = fbscp->fbsc_fbsp;
99  int fd = fbscp->fbsc_fd;
100 
101  curr_fbp = fbsp->fbs_fbp;
102 
103  for (i = MAX_CLIENTS - 1; i >= 0; i--) {
104  if (fbsp->fbs_clients[i].fbsc_fd == 0)
105  continue;
106 
107  if ((pkg_process(fbsp->fbs_clients[i].fbsc_pkg)) < 0)
108  bu_log("pkg_process error encountered (1)\n");
109 
110  if (fbsp->fbs_clients[i].fbsc_fd != fd)
111  continue;
112 
113  if (pkg_suckin(fbsp->fbs_clients[i].fbsc_pkg) <= 0) {
114  /* Probably EOF */
115  drop_client(fbsp, i);
116 
117  continue;
118  }
119 
120  if ((pkg_process(fbsp->fbs_clients[i].fbsc_pkg)) < 0)
121  bu_log("pkg_process error encountered (2)\n");
122  }
123 
124  if (fbsp->fbs_callback != (void (*)(void *))FBS_CALLBACK_NULL) {
125  /* need to cast func pointer explicitly to get the function call */
126  void (*cfp)(void *);
127  cfp = (void (*)(void *))fbsp->fbs_callback;
128  cfp(fbsp->fbs_clientData);
129  }
130 }
131 
132 
133 HIDDEN void
135 {
136  int on = 1;
137  int retval = 0;
138 
139 #if defined(SO_KEEPALIVE)
140  /* FIXME: better to show an error message but need thread considerations for strerror */
141  if ((retval = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof(on))) < 0) {
142  bu_log("setsockopt (SO_KEEPALIVE) error return: %d", retval);
143  }
144 #endif
145 #if defined(SO_RCVBUF)
146  /* try to set our buffers up larger */
147  {
148  int m = -1;
149  int n = -1;
150  int val;
151  int size;
152 
153  for (size = 256; size > 16; size /= 2) {
154  val = size * 1024;
155  m = setsockopt(fd, SOL_SOCKET, SO_RCVBUF,
156  (char *)&val, sizeof(val));
157  val = size * 1024;
158  n = setsockopt(fd, SOL_SOCKET, SO_SNDBUF,
159  (char *)&val, sizeof(val));
160  if (m >= 0 && n >= 0) break;
161  }
162 
163  if (m < 0 || n < 0)
164  bu_log("setup_socket: setsockopt()");
165  }
166 #endif
167 }
168 
169 
170 #if defined(_WIN32) && !defined(__CYGWIN__)
171 HIDDEN void
172 new_client(struct fbserv_obj *fbsp, struct pkg_conn *pcp, Tcl_Channel chan)
173 {
174  int i;
175 
176  if (pcp == PKC_ERROR)
177  return;
178 
179  for (i = MAX_CLIENTS - 1; i >= 0; i--) {
180  /* this slot is being used */
181  if (fbsp->fbs_clients[i].fbsc_fd != 0)
182  continue;
183 
184  /* Found an available slot */
185  fbsp->fbs_clients[i].fbsc_fd = pcp->pkc_fd;
186  fbsp->fbs_clients[i].fbsc_pkg = pcp;
187  fbsp->fbs_clients[i].fbsc_fbsp = fbsp;
188  setup_socket(pcp->pkc_fd);
189 
190  fbsp->fbs_clients[i].fbsc_chan = chan;
191  fbsp->fbs_clients[i].fbsc_handler = existing_client_handler;
192  Tcl_CreateChannelHandler(fbsp->fbs_clients[i].fbsc_chan, TCL_READABLE,
193  fbsp->fbs_clients[i].fbsc_handler,
194  (ClientData)&fbsp->fbs_clients[i]);
195  return;
196  }
197 
198  bu_log("new_client: too many clients\n");
199  pkg_close(pcp);
200 }
201 
202 #else /* if defined(_WIN32) && !defined(__CYGWIN__) */
203 HIDDEN void
204 new_client(struct fbserv_obj *fbsp, struct pkg_conn *pcp, Tcl_Channel UNUSED(chan))
205 {
206  int i;
207 
208  if (pcp == PKC_ERROR)
209  return;
210 
211  for (i = MAX_CLIENTS - 1; i >= 0; i--) {
212  /* this slot is being used */
213  if (fbsp->fbs_clients[i].fbsc_fd != 0)
214  continue;
215 
216  /* Found an available slot */
217  fbsp->fbs_clients[i].fbsc_fd = pcp->pkc_fd;
218  fbsp->fbs_clients[i].fbsc_pkg = pcp;
219  fbsp->fbs_clients[i].fbsc_fbsp = fbsp;
220  setup_socket(pcp->pkc_fd);
221 
222  Tcl_CreateFileHandler(fbsp->fbs_clients[i].fbsc_fd, TCL_READABLE,
223  existing_client_handler, (ClientData)&fbsp->fbs_clients[i]);
224  return;
225  }
226 
227  bu_log("new_client: too many clients\n");
228  pkg_close(pcp);
229 }
230 #endif /* if defined(_WIN32) && !defined(__CYGWIN__) */
231 
232 #if defined(_WIN32) && !defined(__CYGWIN__)
233 HIDDEN struct pkg_conn *
234 fbs_makeconn(int fd, const struct pkg_switch *switchp)
235 {
236  register struct pkg_conn *pc;
237 #ifdef HAVE_WINSOCK_H
238  WSADATA wsaData;
239  WORD wVersionRequested; /* initialize Windows socket networking,
240  * increment reference count.
241  */
242 #endif
243 
244  if ((pc = (struct pkg_conn *)malloc(sizeof(struct pkg_conn))) == PKC_NULL) {
245  comm_error("fbs_makeconn: malloc failure\n");
246  return PKC_ERROR;
247  }
248 
249 #ifdef HAVE_WINSOCK_H
250  wVersionRequested = MAKEWORD(1, 1);
251  if (WSAStartup(wVersionRequested, &wsaData) != 0) {
252  comm_error("fbs_makeconn: could not find a usable WinSock DLL\n");
253  return PKC_ERROR;
254  }
255 #endif
256 
257  memset((char *)pc, 0, sizeof(struct pkg_conn));
258  pc->pkc_magic = PKG_MAGIC;
259  pc->pkc_fd = fd;
260  pc->pkc_switch = switchp;
261  pc->pkc_errlog = 0;
262  pc->pkc_left = -1;
263  pc->pkc_buf = (char *)0;
264  pc->pkc_curpos = (char *)0;
265  pc->pkc_strpos = 0;
266  pc->pkc_incur = pc->pkc_inend = 0;
267 
268  return pc;
269 }
270 #endif
271 
272 
273 /*
274  * This is where we go for message types we don't understand.
275  */
276 HIDDEN void
277 fbs_rfbunknown(struct pkg_conn *pcp, char *buf)
278 {
279  bu_log("fbserv: unable to handle message type %d\n", pcp->pkc_type);
280  if (buf) {
281  (void)free(buf);
282  }
283 }
284 
285 
286 /******** Here's where the hooks lead *********/
287 
288 HIDDEN void
289 fbs_rfbopen(struct pkg_conn *pcp, char *buf)
290 {
291  char rbuf[5*NET_LONG_LEN+1];
292  int want;
293 
294  /* Don't really open a new framebuffer --- use existing one */
295  (void)pkg_plong(&rbuf[0*NET_LONG_LEN], 0); /* ret */
296  (void)pkg_plong(&rbuf[1*NET_LONG_LEN], curr_fbp->if_max_width);
297  (void)pkg_plong(&rbuf[2*NET_LONG_LEN], curr_fbp->if_max_height);
298  (void)pkg_plong(&rbuf[3*NET_LONG_LEN], curr_fbp->if_width);
299  (void)pkg_plong(&rbuf[4*NET_LONG_LEN], curr_fbp->if_height);
300 
301  want = 5*NET_LONG_LEN;
302  if (pkg_send(MSG_RETURN, rbuf, want, pcp) != want)
303  comm_error("pkg_send fb_open reply\n");
304 
305  if (buf) {
306  (void)free(buf);
307  }
308 }
309 
310 
311 void
312 fbs_rfbclose(struct pkg_conn *pcp, char *buf)
313 {
314  char rbuf[NET_LONG_LEN+1];
315 
316  /*
317  * We are playing FB server so we don't really close the frame
318  * buffer. We should flush output however.
319  */
320  (void)fb_flush(curr_fbp);
321  (void)pkg_plong(&rbuf[0], 0); /* return success */
322 
323  /* Don't check for errors, linger mode or other events may have
324  * already closed down all the file descriptors. If communication
325  * has broken, other end will know we are gone.
326  */
327  (void)pkg_send(MSG_RETURN, rbuf, NET_LONG_LEN, pcp);
328 
329  if (buf) {
330  (void)free(buf);
331  }
332 }
333 
334 
335 void
336 fbs_rfbfree(struct pkg_conn *pcp, char *buf)
337 {
338  char rbuf[NET_LONG_LEN+1];
339 
340  /* Don't really free framebuffer */
341  if (pkg_send(MSG_RETURN, rbuf, NET_LONG_LEN, pcp) != NET_LONG_LEN)
342  comm_error("pkg_send fb_free reply\n");
343 
344  if (buf) {
345  (void)free(buf);
346  }
347 }
348 
349 
350 void
351 fbs_rfbclear(struct pkg_conn *pcp, char *buf)
352 {
353  RGBpixel bg;
354  char rbuf[NET_LONG_LEN+1];
355 
356  if (!buf) {
357  bu_log("fbs_rfbclear: null buffer\n");
358  return;
359  }
360 
361  bg[RED] = buf[0];
362  bg[GRN] = buf[1];
363  bg[BLU] = buf[2];
364 
365  (void)pkg_plong(rbuf, fb_clear(curr_fbp, bg));
366  pkg_send(MSG_RETURN, rbuf, NET_LONG_LEN, pcp);
367 
368  (void)free(buf);
369 }
370 
371 
372 void
373 fbs_rfbread(struct pkg_conn *pcp, char *buf)
374 {
375  int x, y;
376  size_t num;
377  int ret;
378  static unsigned char *scanbuf = NULL;
379  static size_t buflen = 0;
380 
381  if (!buf) {
382  bu_log("fbs_rfbread: null buffer\n");
383  return;
384  }
385 
386  x = pkg_glong(&buf[0*NET_LONG_LEN]);
387  y = pkg_glong(&buf[1*NET_LONG_LEN]);
388  num = (size_t)pkg_glong(&buf[2*NET_LONG_LEN]);
389 
390  if (num*sizeof(RGBpixel) > buflen) {
391  if (scanbuf != NULL)
392  free((char *)scanbuf);
393  buflen = num*sizeof(RGBpixel);
394  if (buflen < 1024*sizeof(RGBpixel))
395  buflen = 1024*sizeof(RGBpixel);
396  if ((scanbuf = (unsigned char *)malloc(buflen)) == NULL) {
397  fb_log("fb_read: malloc failed!");
398  (void)free(buf);
399  buflen = 0;
400  return;
401  }
402  }
403 
404  ret = fb_read(curr_fbp, x, y, scanbuf, num);
405  if (ret < 0) ret = 0; /* map error indications */
406  /* sending a 0-length package indicates error */
407  pkg_send(MSG_RETURN, (char *)scanbuf, ret*sizeof(RGBpixel), pcp);
408  (void)free(buf);
409 }
410 
411 
412 void
413 fbs_rfbwrite(struct pkg_conn *pcp, char *buf)
414 {
415  long x, y, num;
416  char rbuf[NET_LONG_LEN+1];
417  int ret;
418  int type;
419 
420  if (!buf) {
421  bu_log("fbs_rfbwrite: null buffer\n");
422  return;
423  }
424 
425  x = pkg_glong(&buf[0*NET_LONG_LEN]);
426  y = pkg_glong(&buf[1*NET_LONG_LEN]);
427  num = pkg_glong(&buf[2*NET_LONG_LEN]);
428  type = pcp->pkc_type;
429  ret = fb_write(curr_fbp, x, y, (unsigned char *)&buf[3*NET_LONG_LEN], (size_t)num);
430 
431  if (type < MSG_NORETURN) {
432  (void)pkg_plong(&rbuf[0*NET_LONG_LEN], ret);
433  pkg_send(MSG_RETURN, rbuf, NET_LONG_LEN, pcp);
434  }
435  (void)free(buf);
436 }
437 
438 
439 void
440 fbs_rfbreadrect(struct pkg_conn *pcp, char *buf)
441 {
442  int xmin, ymin;
443  int width, height;
444  size_t num;
445  int ret;
446  static unsigned char *scanbuf = NULL;
447  static size_t buflen = 0;
448 
449  if (!buf) {
450  bu_log("fbs_rfbreadrect: null buffer\n");
451  return;
452  }
453 
454  xmin = pkg_glong(&buf[0*NET_LONG_LEN]);
455  ymin = pkg_glong(&buf[1*NET_LONG_LEN]);
456  width = pkg_glong(&buf[2*NET_LONG_LEN]);
457  height = pkg_glong(&buf[3*NET_LONG_LEN]);
458  num = width * height;
459 
460  if (num*sizeof(RGBpixel) > buflen) {
461  if (scanbuf != NULL)
462  free((char *)scanbuf);
463  buflen = num*sizeof(RGBpixel);
464  if (buflen < 1024*sizeof(RGBpixel))
465  buflen = 1024*sizeof(RGBpixel);
466  if ((scanbuf = (unsigned char *)malloc(buflen)) == NULL) {
467  fb_log("fb_read: malloc failed!");
468  (void)free(buf);
469  buflen = 0;
470  return;
471  }
472  }
473 
474  ret = fb_readrect(curr_fbp, xmin, ymin, width, height, scanbuf);
475  if (ret < 0) ret = 0; /* map error indications */
476  /* sending a 0-length package indicates error */
477  pkg_send(MSG_RETURN, (char *)scanbuf, ret*sizeof(RGBpixel), pcp);
478  (void)free(buf);
479 }
480 
481 
482 void
483 fbs_rfbwriterect(struct pkg_conn *pcp, char *buf)
484 {
485  int x, y;
486  int width, height;
487  char rbuf[NET_LONG_LEN+1];
488  int ret;
489  int type;
490 
491  if (!buf) {
492  bu_log("fbs_rfbwriterect: null buffer\n");
493  return;
494  }
495 
496  x = pkg_glong(&buf[0*NET_LONG_LEN]);
497  y = pkg_glong(&buf[1*NET_LONG_LEN]);
498  width = pkg_glong(&buf[2*NET_LONG_LEN]);
499  height = pkg_glong(&buf[3*NET_LONG_LEN]);
500 
501  type = pcp->pkc_type;
502  ret = fb_writerect(curr_fbp, x, y, width, height,
503  (unsigned char *)&buf[4*NET_LONG_LEN]);
504 
505  if (type < MSG_NORETURN) {
506  (void)pkg_plong(&rbuf[0*NET_LONG_LEN], ret);
507  pkg_send(MSG_RETURN, rbuf, NET_LONG_LEN, pcp);
508  }
509  (void)free(buf);
510 }
511 
512 
513 void
514 fbs_rfbbwreadrect(struct pkg_conn *pcp, char *buf)
515 {
516  int xmin, ymin;
517  int width, height;
518  int num;
519  int ret;
520  static unsigned char *scanbuf = NULL;
521  static int buflen = 0;
522 
523  if (!buf) {
524  bu_log("fbs_rfbbwreadrect: null buffer\n");
525  return;
526  }
527 
528  xmin = pkg_glong(&buf[0*NET_LONG_LEN]);
529  ymin = pkg_glong(&buf[1*NET_LONG_LEN]);
530  width = pkg_glong(&buf[2*NET_LONG_LEN]);
531  height = pkg_glong(&buf[3*NET_LONG_LEN]);
532  num = width * height;
533 
534  if (num > buflen) {
535  if (scanbuf != NULL)
536  free((char *)scanbuf);
537  buflen = num;
538  if (buflen < 1024)
539  buflen = 1024;
540  if ((scanbuf = (unsigned char *)malloc(buflen)) == NULL) {
541  fb_log("fbs_rfbbwreadrect: malloc failed!");
542  (void)free(buf);
543  buflen = 0;
544  return;
545  }
546  }
547 
548  ret = fb_bwreadrect(curr_fbp, xmin, ymin, width, height, scanbuf);
549  if (ret < 0) ret = 0; /* map error indications */
550  /* sending a 0-length package indicates error */
551  pkg_send(MSG_RETURN, (char *)scanbuf, ret, pcp);
552  (void)free(buf);
553 }
554 
555 
556 void
557 fbs_rfbbwwriterect(struct pkg_conn *pcp, char *buf)
558 {
559  int x, y;
560  int width, height;
561  char rbuf[NET_LONG_LEN+1];
562  int ret;
563  int type;
564 
565  if (!buf) {
566  bu_log("fbs_rfbbwwriterect: null buffer\n");
567  return;
568  }
569 
570  x = pkg_glong(&buf[0*NET_LONG_LEN]);
571  y = pkg_glong(&buf[1*NET_LONG_LEN]);
572  width = pkg_glong(&buf[2*NET_LONG_LEN]);
573  height = pkg_glong(&buf[3*NET_LONG_LEN]);
574 
575  type = pcp->pkc_type;
576  ret = fb_writerect(curr_fbp, x, y, width, height,
577  (unsigned char *)&buf[4*NET_LONG_LEN]);
578 
579  if (type < MSG_NORETURN) {
580  (void)pkg_plong(&rbuf[0*NET_LONG_LEN], ret);
581  pkg_send(MSG_RETURN, rbuf, NET_LONG_LEN, pcp);
582  }
583  (void)free(buf);
584 }
585 
586 
587 void
588 fbs_rfbcursor(struct pkg_conn *pcp, char *buf)
589 {
590  int mode, x, y;
591  char rbuf[NET_LONG_LEN+1];
592 
593  if (!buf) {
594  bu_log("fbs_rfbcursor: null buffer\n");
595  return;
596  }
597 
598  mode = pkg_glong(&buf[0*NET_LONG_LEN]);
599  x = pkg_glong(&buf[1*NET_LONG_LEN]);
600  y = pkg_glong(&buf[2*NET_LONG_LEN]);
601 
602  (void)pkg_plong(&rbuf[0], fb_cursor(curr_fbp, mode, x, y));
603  pkg_send(MSG_RETURN, rbuf, NET_LONG_LEN, pcp);
604  (void)free(buf);
605 }
606 
607 
608 void
609 fbs_rfbgetcursor(struct pkg_conn *pcp, char *buf)
610 {
611  int ret;
612  int mode, x, y;
613  char rbuf[4*NET_LONG_LEN+1];
614 
615  ret = fb_getcursor(curr_fbp, &mode, &x, &y);
616  (void)pkg_plong(&rbuf[0*NET_LONG_LEN], ret);
617  (void)pkg_plong(&rbuf[1*NET_LONG_LEN], mode);
618  (void)pkg_plong(&rbuf[2*NET_LONG_LEN], x);
619  (void)pkg_plong(&rbuf[3*NET_LONG_LEN], y);
620  pkg_send(MSG_RETURN, rbuf, 4*NET_LONG_LEN, pcp);
621 
622  if (buf) {
623  (void)free(buf);
624  }
625 }
626 
627 
628 void
629 fbs_rfbsetcursor(struct pkg_conn *pcp, char *buf)
630 {
631  char rbuf[NET_LONG_LEN+1];
632  int ret;
633  int xbits, ybits;
634  int xorig, yorig;
635 
636  if (!buf) {
637  bu_log("fbs_rfsetcursor: null buffer\n");
638  return;
639  }
640 
641  xbits = pkg_glong(&buf[0*NET_LONG_LEN]);
642  ybits = pkg_glong(&buf[1*NET_LONG_LEN]);
643  xorig = pkg_glong(&buf[2*NET_LONG_LEN]);
644  yorig = pkg_glong(&buf[3*NET_LONG_LEN]);
645 
646  ret = fb_setcursor(curr_fbp, (unsigned char *)&buf[4*NET_LONG_LEN],
647  xbits, ybits, xorig, yorig);
648 
649  if (pcp->pkc_type < MSG_NORETURN) {
650  (void)pkg_plong(&rbuf[0*NET_LONG_LEN], ret);
651  pkg_send(MSG_RETURN, rbuf, NET_LONG_LEN, pcp);
652  }
653  (void)free(buf);
654 }
655 
656 
657 /*OLD*/
658 void
659 fbs_rfbscursor(struct pkg_conn *pcp, char *buf)
660 {
661  int mode, x, y;
662  char rbuf[NET_LONG_LEN+1];
663 
664  if (!buf) {
665  bu_log("fbs_rfbscursor: null buffer\n");
666  return;
667  }
668 
669  mode = pkg_glong(&buf[0*NET_LONG_LEN]);
670  x = pkg_glong(&buf[1*NET_LONG_LEN]);
671  y = pkg_glong(&buf[2*NET_LONG_LEN]);
672 
673  (void)pkg_plong(&rbuf[0], fb_scursor(curr_fbp, mode, x, y));
674  pkg_send(MSG_RETURN, rbuf, NET_LONG_LEN, pcp);
675  (void)free(buf);
676 }
677 
678 
679 /*OLD*/
680 void
681 fbs_rfbwindow(struct pkg_conn *pcp, char *buf)
682 {
683  int x, y;
684  char rbuf[NET_LONG_LEN+1];
685 
686  if (!buf) {
687  bu_log("fbs_rfbwindow: null buffer\n");
688  return;
689  }
690 
691  x = pkg_glong(&buf[0*NET_LONG_LEN]);
692  y = pkg_glong(&buf[1*NET_LONG_LEN]);
693 
694  (void)pkg_plong(&rbuf[0], fb_window(curr_fbp, x, y));
695  pkg_send(MSG_RETURN, rbuf, NET_LONG_LEN, pcp);
696 
697  (void)free(buf);
698 }
699 
700 
701 /*OLD*/
702 void
703 fbs_rfbzoom(struct pkg_conn *pcp, char *buf)
704 {
705  int x, y;
706  char rbuf[NET_LONG_LEN+1];
707 
708  if (!buf) {
709  bu_log("fbs_rfbzoom: null buffer\n");
710  return;
711  }
712 
713  x = pkg_glong(&buf[0*NET_LONG_LEN]);
714  y = pkg_glong(&buf[1*NET_LONG_LEN]);
715 
716  (void)pkg_plong(&rbuf[0], fb_zoom(curr_fbp, x, y));
717  pkg_send(MSG_RETURN, rbuf, NET_LONG_LEN, pcp);
718  (void)free(buf);
719 }
720 
721 
722 void
723 fbs_rfbview(struct pkg_conn *pcp, char *buf)
724 {
725  int ret;
726  int xcenter, ycenter, xzoom, yzoom;
727  char rbuf[NET_LONG_LEN+1];
728 
729  if (!buf) {
730  bu_log("fbs_rfbview: null buffer\n");
731  return;
732  }
733 
734  xcenter = pkg_glong(&buf[0*NET_LONG_LEN]);
735  ycenter = pkg_glong(&buf[1*NET_LONG_LEN]);
736  xzoom = pkg_glong(&buf[2*NET_LONG_LEN]);
737  yzoom = pkg_glong(&buf[3*NET_LONG_LEN]);
738 
739  ret = fb_view(curr_fbp, xcenter, ycenter, xzoom, yzoom);
740  (void)pkg_plong(&rbuf[0], ret);
741  pkg_send(MSG_RETURN, rbuf, NET_LONG_LEN, pcp);
742  (void)free(buf);
743 }
744 
745 
746 void
747 fbs_rfbgetview(struct pkg_conn *pcp, char *buf)
748 {
749  int ret;
750  int xcenter, ycenter, xzoom, yzoom;
751  char rbuf[5*NET_LONG_LEN+1];
752 
753  ret = fb_getview(curr_fbp, &xcenter, &ycenter, &xzoom, &yzoom);
754  (void)pkg_plong(&rbuf[0*NET_LONG_LEN], ret);
755  (void)pkg_plong(&rbuf[1*NET_LONG_LEN], xcenter);
756  (void)pkg_plong(&rbuf[2*NET_LONG_LEN], ycenter);
757  (void)pkg_plong(&rbuf[3*NET_LONG_LEN], xzoom);
758  (void)pkg_plong(&rbuf[4*NET_LONG_LEN], yzoom);
759  pkg_send(MSG_RETURN, rbuf, 5*NET_LONG_LEN, pcp);
760 
761  if (buf) {
762  (void)free(buf);
763  }
764 }
765 
766 
767 void
768 fbs_rfbrmap(struct pkg_conn *pcp, char *buf)
769 {
770  register int i;
771  char rbuf[NET_LONG_LEN+1];
772  ColorMap map;
773  unsigned char cm[256*2*3];
774 
775  (void)pkg_plong(&rbuf[0*NET_LONG_LEN], fb_rmap(curr_fbp, &map));
776  for (i = 0; i < 256; i++) {
777  (void)pkg_pshort((char *)(cm+2*(0+i)), map.cm_red[i]);
778  (void)pkg_pshort((char *)(cm+2*(256+i)), map.cm_green[i]);
779  (void)pkg_pshort((char *)(cm+2*(512+i)), map.cm_blue[i]);
780  }
781  pkg_send(MSG_DATA, (char *)cm, sizeof(cm), pcp);
782  pkg_send(MSG_RETURN, rbuf, NET_LONG_LEN, pcp);
783 
784  if (buf) {
785  (void)free(buf);
786  }
787 }
788 
789 
790 /*
791  * Accept a color map sent by the client, and write it to the
792  * framebuffer. Network format is to send each entry as a network
793  * (IBM) order 2-byte short, 256 red shorts, followed by 256 green and
794  * 256 blue, for a total of 3*256*2 bytes.
795  */
796 void
797 fbs_rfbwmap(struct pkg_conn *pcp, char *buf)
798 {
799  int i;
800  char rbuf[NET_LONG_LEN+1];
801  long ret;
802  ColorMap map;
803 
804  if (!buf) {
805  bu_log("fbs_rfbwmap: null buffer\n");
806  return;
807  }
808 
809  if (pcp->pkc_len == 0) {
810  ret = fb_wmap(curr_fbp, COLORMAP_NULL);
811  } else {
812  for (i = 0; i < 256; i++) {
813  map.cm_red[i] = pkg_gshort(buf+2*(0+i));
814  map.cm_green[i] = pkg_gshort(buf+2*(256+i));
815  map.cm_blue[i] = pkg_gshort(buf+2*(512+i));
816  }
817  ret = fb_wmap(curr_fbp, &map);
818  }
819  (void)pkg_plong(&rbuf[0], ret);
820  pkg_send(MSG_RETURN, rbuf, NET_LONG_LEN, pcp);
821  (void)free(buf);
822 }
823 
824 
825 void
826 fbs_rfbflush(struct pkg_conn *pcp, char *buf)
827 {
828  int ret;
829  char rbuf[NET_LONG_LEN+1];
830 
831  ret = fb_flush(curr_fbp);
832 
833  if (pcp->pkc_type < MSG_NORETURN) {
834  (void)pkg_plong(rbuf, ret);
835  pkg_send(MSG_RETURN, rbuf, NET_LONG_LEN, pcp);
836  }
837 
838  if (buf) {
839  (void)free(buf);
840  }
841 }
842 
843 
844 void
845 fbs_rfbpoll(struct pkg_conn *pcp, char *buf)
846 {
847  if (pcp == PKC_ERROR) {
848  return;
849  }
850 
851  (void)fb_poll(curr_fbp);
852  if (buf) {
853  (void)free(buf);
854  }
855 }
856 
857 
858 /*
859  * At one time at least we couldn't send a zero length PKG message
860  * back and forth, so we receive a dummy long here.
861  */
862 void
863 fbs_rfbhelp(struct pkg_conn *pcp, char *buf)
864 {
865  long ret;
866  char rbuf[NET_LONG_LEN+1];
867 
868  if (!buf) {
869  bu_log("fbs_rfbhelp: null buffer\n");
870  return;
871  }
872 
873  (void)pkg_glong(&buf[0*NET_LONG_LEN]);
874 
875  ret = fb_help(curr_fbp);
876  (void)pkg_plong(&rbuf[0], ret);
877  pkg_send(MSG_RETURN, rbuf, NET_LONG_LEN, pcp);
878  (void)free(buf);
879 }
880 
881 
882 /*
883  * Accept any new client connections.
884  */
885 #if defined(_WIN32) && !defined(__CYGWIN__)
886 HIDDEN void
887 new_client_handler(ClientData clientData,
888  Tcl_Channel chan,
889  char *UNUSED(host),
890  int UNUSED(port))
891 {
892  struct fbserv_listener *fbslp = (struct fbserv_listener *)clientData;
893  struct fbserv_obj *fbsp = fbslp->fbsl_fbsp;
894  uintptr_t fd = (uintptr_t)fbslp->fbsl_fd;
895 
896  static struct pkg_switch pswitch[] = {
897  { MSG_FBOPEN, fbs_rfbopen, "Open Framebuffer", NULL },
898  { MSG_FBCLOSE, fbs_rfbclose, "Close Framebuffer", NULL },
899  { MSG_FBCLEAR, fbs_rfbclear, "Clear Framebuffer", NULL },
900  { MSG_FBREAD, fbs_rfbread, "Read Pixels", NULL },
901  { MSG_FBWRITE, fbs_rfbwrite, "Write Pixels", NULL },
902  { MSG_FBWRITE + MSG_NORETURN, fbs_rfbwrite, "Asynch write", NULL },
903  { MSG_FBCURSOR, fbs_rfbcursor, "Cursor", NULL },
904  { MSG_FBGETCURSOR, fbs_rfbgetcursor, "Get Cursor", NULL }, /*NEW*/
905  { MSG_FBSCURSOR, fbs_rfbscursor, "Screen Cursor", NULL }, /*OLD*/
906  { MSG_FBWINDOW, fbs_rfbwindow, "Window", NULL }, /*OLD*/
907  { MSG_FBZOOM, fbs_rfbzoom, "Zoom", NULL }, /*OLD*/
908  { MSG_FBVIEW, fbs_rfbview, "View", NULL }, /*NEW*/
909  { MSG_FBGETVIEW, fbs_rfbgetview, "Get View", NULL }, /*NEW*/
910  { MSG_FBRMAP, fbs_rfbrmap, "R Map", NULL },
911  { MSG_FBWMAP, fbs_rfbwmap, "W Map", NULL },
912  { MSG_FBHELP, fbs_rfbhelp, "Help Request", NULL },
913  { MSG_ERROR, fbs_rfbunknown, "Error Message", NULL },
914  { MSG_CLOSE, fbs_rfbunknown, "Close Connection", NULL },
915  { MSG_FBREADRECT, fbs_rfbreadrect, "Read Rectangle", NULL },
916  { MSG_FBWRITERECT, fbs_rfbwriterect, "Write Rectangle", NULL },
917  { MSG_FBWRITERECT + MSG_NORETURN, fbs_rfbwriterect, "Write Rectangle", NULL },
918  { MSG_FBBWREADRECT, fbs_rfbbwreadrect, "Read BW Rectangle", NULL },
919  { MSG_FBBWWRITERECT, fbs_rfbbwwriterect, "Write BW Rectangle", NULL },
920  { MSG_FBBWWRITERECT+MSG_NORETURN, fbs_rfbbwwriterect, "Write BW Rectangle", NULL },
921  { MSG_FBFLUSH, fbs_rfbflush, "Flush Output", NULL },
922  { MSG_FBFLUSH + MSG_NORETURN, fbs_rfbflush, "Flush Output", NULL },
923  { MSG_FBFREE, fbs_rfbfree, "Free Resources", NULL },
924  { MSG_FBPOLL, fbs_rfbpoll, "Handle Events", NULL },
925  { MSG_FBSETCURSOR, fbs_rfbsetcursor, "Set Cursor Shape", NULL },
926  { MSG_FBSETCURSOR + MSG_NORETURN, fbs_rfbsetcursor, "Set Cursor Shape", NULL },
927  { 0, NULL, NULL, NULL }
928  };
929 
930  if (Tcl_GetChannelHandle(chan, TCL_READABLE, (ClientData *)&fd) == TCL_OK)
931  new_client(fbsp, fbs_makeconn((int)fd, pswitch), chan);
932 }
933 #else /* if defined(_WIN32) && !defined(__CYGWIN__) */
934 HIDDEN void
935 new_client_handler(ClientData clientData,
936  Tcl_Channel UNUSED(chan),
937  char *UNUSED(host),
938  int UNUSED(port))
939 {
940  struct fbserv_listener *fbslp = (struct fbserv_listener *)clientData;
941  struct fbserv_obj *fbsp = fbslp->fbsl_fbsp;
942  int fd = fbslp->fbsl_fd;
943 
944  static struct pkg_switch pswitch[] = {
945  { MSG_FBOPEN, fbs_rfbopen, "Open Framebuffer", NULL },
946  { MSG_FBCLOSE, fbs_rfbclose, "Close Framebuffer", NULL },
947  { MSG_FBCLEAR, fbs_rfbclear, "Clear Framebuffer", NULL },
948  { MSG_FBREAD, fbs_rfbread, "Read Pixels", NULL },
949  { MSG_FBWRITE, fbs_rfbwrite, "Write Pixels", NULL },
950  { MSG_FBWRITE + MSG_NORETURN, fbs_rfbwrite, "Asynch write", NULL },
951  { MSG_FBCURSOR, fbs_rfbcursor, "Cursor", NULL },
952  { MSG_FBGETCURSOR, fbs_rfbgetcursor, "Get Cursor", NULL }, /*NEW*/
953  { MSG_FBSCURSOR, fbs_rfbscursor, "Screen Cursor", NULL }, /*OLD*/
954  { MSG_FBWINDOW, fbs_rfbwindow, "Window", NULL }, /*OLD*/
955  { MSG_FBZOOM, fbs_rfbzoom, "Zoom", NULL }, /*OLD*/
956  { MSG_FBVIEW, fbs_rfbview, "View", NULL }, /*NEW*/
957  { MSG_FBGETVIEW, fbs_rfbgetview, "Get View", NULL }, /*NEW*/
958  { MSG_FBRMAP, fbs_rfbrmap, "R Map", NULL },
959  { MSG_FBWMAP, fbs_rfbwmap, "W Map", NULL },
960  { MSG_FBHELP, fbs_rfbhelp, "Help Request", NULL },
961  { MSG_ERROR, fbs_rfbunknown, "Error Message", NULL },
962  { MSG_CLOSE, fbs_rfbunknown, "Close Connection", NULL },
963  { MSG_FBREADRECT, fbs_rfbreadrect, "Read Rectangle", NULL },
964  { MSG_FBWRITERECT, fbs_rfbwriterect, "Write Rectangle", NULL },
965  { MSG_FBWRITERECT + MSG_NORETURN, fbs_rfbwriterect, "Write Rectangle", NULL },
966  { MSG_FBBWREADRECT, fbs_rfbbwreadrect, "Read BW Rectangle", NULL },
967  { MSG_FBBWWRITERECT, fbs_rfbbwwriterect, "Write BW Rectangle", NULL },
968  { MSG_FBBWWRITERECT+MSG_NORETURN, fbs_rfbbwwriterect, "Write BW Rectangle", NULL },
969  { MSG_FBFLUSH, fbs_rfbflush, "Flush Output", NULL },
970  { MSG_FBFLUSH + MSG_NORETURN, fbs_rfbflush, "Flush Output", NULL },
971  { MSG_FBFREE, fbs_rfbfree, "Free Resources", NULL },
972  { MSG_FBPOLL, fbs_rfbpoll, "Handle Events", NULL },
973  { MSG_FBSETCURSOR, fbs_rfbsetcursor, "Set Cursor Shape", NULL },
974  { MSG_FBSETCURSOR + MSG_NORETURN, fbs_rfbsetcursor, "Set Cursor Shape", NULL },
975  { 0, NULL, NULL, NULL }
976  };
977 
978  new_client(fbsp, pkg_getclient(fd, pswitch, comm_error, 0), 0);
979 }
980 #endif /* if defined(_WIN32) && !defined(__CYGWIN__) */
981 
982 int
983 fbs_open(struct fbserv_obj *fbsp, int port)
984 {
985  int i;
986  struct bu_vls vls = BU_VLS_INIT_ZERO;
987  char hostname[32] = {0};
988  Tcl_DString ds;
989  int failed = 0;
990  int available_port = port;
991 
992  /* Already listening; nothing more to do. */
993 #if defined(_WIN32) && !defined(__CYGWIN__)
994  if (fbsp->fbs_listener.fbsl_chan != NULL) {
995  return TCL_OK;
996  }
997 #else /* if defined(_WIN32) && !defined(__CYGWIN__) */
998  if (fbsp->fbs_listener.fbsl_fd >= 0) {
999  return TCL_OK;
1000  }
1001 #endif /* if defined(_WIN32) && !defined(__CYGWIN__) */
1002 
1003  /* XXX hardwired for now */
1004  sprintf(hostname, "localhost");
1005 
1006  if (available_port < 0) {
1007  available_port = 5559;
1008  } else if (available_port < 1024) {
1009  available_port += 5559;
1010  }
1011 
1012  Tcl_DStringInit(&ds);
1013 
1014  /* Try a reasonable number of times to hang a listen */
1015  for (i = 0; i < MAX_PORT_TRIES; ++i) {
1016  /*
1017  * Hang an unending listen for PKG connections
1018  */
1019 #if defined(_WIN32) && !defined(__CYGWIN__)
1020  fbsp->fbs_listener.fbsl_chan = Tcl_OpenTcpServer(fbsp->fbs_interp, available_port, hostname, new_client_handler, (ClientData)&fbsp->fbs_listener);
1021  if (fbsp->fbs_listener.fbsl_chan == NULL) {
1022  /* This clobbers the result string which probably has junk
1023  * related to the failed open.
1024  */
1025  Tcl_DStringResult(fbsp->fbs_interp, &ds);
1026  } else {
1027  break;
1028  }
1029 #else /* if defined(_WIN32) && !defined(__CYGWIN__) */
1030  char portname[32] = {0};
1031  sprintf(portname, "%d", available_port);
1032  fbsp->fbs_listener.fbsl_fd = pkg_permserver(portname, 0, 0, comm_error);
1033  if (fbsp->fbs_listener.fbsl_fd >= 0)
1034  break;
1035 #endif /* if defined(_WIN32) && !defined(__CYGWIN__) */
1036 
1037  ++available_port;
1038  }
1039 
1040 #if defined(_WIN32) && !defined(__CYGWIN__)
1041  if (fbsp->fbs_listener.fbsl_chan == NULL) {
1042  failed = 1;
1043  }
1044 #else /* if defined(_WIN32) && !defined(__CYGWIN__) */
1045  if (fbsp->fbs_listener.fbsl_fd < 0) {
1046  failed = 1;
1047  }
1048 #endif /* if defined(_WIN32) && !defined(__CYGWIN__) */
1049 
1050  if (failed) {
1051  bu_vls_printf(&vls, "fbs_open: failed to hang a listen on ports %d - %d\n", port, available_port);
1052  Tcl_AppendResult(fbsp->fbs_interp, bu_vls_addr(&vls), (char *)NULL);
1053  bu_vls_free(&vls);
1054 
1055  fbsp->fbs_listener.fbsl_port = -1;
1056 
1057  return TCL_ERROR;
1058  }
1059 
1060  fbsp->fbs_listener.fbsl_port = available_port;
1061 
1062 #if defined(_WIN32) && !defined(__CYGWIN__)
1063  Tcl_GetChannelHandle(fbsp->fbs_listener.fbsl_chan, TCL_READABLE, (ClientData *)&fbsp->fbs_listener.fbsl_fd);
1064 #else /* if defined(_WIN32) && !defined(__CYGWIN__) */
1065  Tcl_CreateFileHandler(fbsp->fbs_listener.fbsl_fd, TCL_READABLE, (Tcl_FileProc *)new_client_handler, (ClientData)&fbsp->fbs_listener);
1066 #endif /* if defined(_WIN32) && !defined(__CYGWIN__) */
1067 
1068  return TCL_OK;
1069 }
1070 
1071 
1072 int
1073 fbs_close(struct fbserv_obj *fbsp)
1074 {
1075  int i;
1076 
1077  /* first drop all clients */
1078  for (i = 0; i < MAX_CLIENTS; ++i)
1079  drop_client(fbsp, i);
1080 
1081 #if defined(_WIN32) && !defined(__CYGWIN__)
1082  if (fbsp->fbs_listener.fbsl_chan != NULL) {
1083  Tcl_ChannelProc *callback = (Tcl_ChannelProc *)new_client_handler;
1084  Tcl_DeleteChannelHandler(fbsp->fbs_listener.fbsl_chan, callback, (ClientData)fbsp->fbs_listener.fbsl_fd);
1085  Tcl_Close(fbsp->fbs_interp, fbsp->fbs_listener.fbsl_chan);
1086  fbsp->fbs_listener.fbsl_chan = NULL;
1087  }
1088 #else
1089  Tcl_DeleteFileHandler(fbsp->fbs_listener.fbsl_fd);
1090 #endif
1091 
1092  if (0 <= fbsp->fbs_listener.fbsl_fd)
1093  close(fbsp->fbs_listener.fbsl_fd);
1094  fbsp->fbs_listener.fbsl_fd = -1;
1095  fbsp->fbs_listener.fbsl_port = -1;
1096 
1097  return TCL_OK;
1098 }
1099 
1100 
1101 /*
1102  * Local Variables:
1103  * mode: C
1104  * tab-width: 8
1105  * indent-tabs-mode: t
1106  * c-file-style: "stroustrup"
1107  * End:
1108  * ex: shiftwidth=4 tabstop=8
1109  */
const struct pkg_switch * pkc_switch
Array of message handlers.
Definition: pkg.h:81
Definition: db_flip.c:35
int pkc_incur
current pos in inbuf
Definition: pkg.h:93
void fbs_rfbread(struct pkg_conn *pcp, char *buf)
Definition: fbserv_obj.c:373
#define COLORMAP_NULL
Definition: fb.h:91
unsigned char RGBpixel[3]
Definition: fb.h:73
void bu_log(const char *,...) _BU_ATTR_PRINTF12
Definition: log.c:176
char * pkg_plong(char *buf, unsigned long l)
Definition: pkg.c:190
void pkg_close(struct pkg_conn *pc)
Definition: pkg.c:800
HIDDEN void fbs_rfbopen(struct pkg_conn *pcp, char *buf)
Definition: fbserv_obj.c:289
void fb_log(const char *fmt,...) _BU_ATTR_PRINTF12
Definition: fb_log.c:42
unsigned short cm_green[256]
Definition: fb.h:84
int fb_help(fb *ifp)
Definition: fb_generic.c:260
void fbs_rfbcursor(struct pkg_conn *pcp, char *buf)
Definition: fbserv_obj.c:588
void fbs_rfbfree(struct pkg_conn *pcp, char *buf)
Definition: fbserv_obj.c:336
pkg_errlog pkc_errlog
Error message logger.
Definition: pkg.h:82
#define RED
Definition: color.h:39
void fbs_rfbbwwriterect(struct pkg_conn *pcp, char *buf)
Definition: fbserv_obj.c:557
void fbs_rfbgetview(struct pkg_conn *pcp, char *buf)
Definition: fbserv_obj.c:747
Header file for the BRL-CAD common definitions.
HIDDEN void setup_socket(int fd)
Definition: fbserv_obj.c:134
int fb_zoom(fb *ifp, int xzoom, int yzoom)
Definition: fb_util.c:151
int fbs_close(struct fbserv_obj *fbsp)
Definition: fbserv_obj.c:1073
int fb_getcursor(fb *ifp, int *mode, int *x, int *y)
Definition: fb_generic.c:304
int if_max_width
max device width
Definition: fb_private.h:111
int fb_window(fb *ifp, int xcenter, int ycenter)
Definition: fb_util.c:133
int pkc_inend
first unused pos in inbuf
Definition: pkg.h:94
int pkg_process(struct pkg_conn *)
Definition: pkg.c:1560
HIDDEN void fbs_rfbunknown(struct pkg_conn *pcp, char *buf)
Definition: fbserv_obj.c:277
#define BLU
Definition: color.h:41
HIDDEN void drop_client(struct fbserv_obj *fbsp, int sub)
Definition: fbserv_obj.c:68
ustring width
int fb_cursor(fb *ifp, int mode, int x, int y)
Definition: fb_generic.c:300
int pkc_fd
TCP connection fd.
Definition: pkg.h:80
#define HIDDEN
Definition: common.h:86
void fbs_rfbbwreadrect(struct pkg_conn *pcp, char *buf)
Definition: fbserv_obj.c:514
unsigned short pkc_type
pkg_type, in host order
Definition: pkg.h:85
void fbs_rfbhelp(struct pkg_conn *pcp, char *buf)
Definition: fbserv_obj.c:863
void bu_vls_free(struct bu_vls *vp)
Definition: vls.c:248
void fbs_rfbwriterect(struct pkg_conn *pcp, char *buf)
Definition: fbserv_obj.c:483
void * memset(void *s, int c, size_t n)
#define PKG_MAGIC
Definition: pkg.h:71
int pkg_send(int type, const char *buf, size_t len, struct pkg_conn *pc)
Definition: pkg.c:934
#define NET_LONG_LEN
Definition: if_remote.c:64
unsigned int pkc_magic
for validating pointers
Definition: pkg.h:89
int fb_scursor(fb *ifp, int mode, int x, int y)
Definition: fb_util.c:170
int pkc_left
bytes pkg_get expects
Definition: pkg.h:97
int fb_view(fb *ifp, int xcenter, int ycenter, int xzoom, int yzoom)
Definition: fb_generic.c:288
void fbs_rfbflush(struct pkg_conn *pcp, char *buf)
Definition: fbserv_obj.c:826
char * pkg_pshort(char *buf, unsigned short s)
Definition: pkg.c:181
unsigned short cm_red[256]
Definition: fb.h:83
HIDDEN void existing_client_handler(ClientData clientData, int mask)
Definition: fbserv_obj.c:94
#define PKC_NULL
Definition: pkg.h:103
void fbs_rfbview(struct pkg_conn *pcp, char *buf)
Definition: fbserv_obj.c:723
int if_max_height
max device height
Definition: fb_private.h:112
#define UNUSED(parameter)
Definition: common.h:239
void fbs_rfbclose(struct pkg_conn *pcp, char *buf)
Definition: fbserv_obj.c:312
int pkc_strpos
index into stream buffer
Definition: pkg.h:90
char * bu_vls_addr(const struct bu_vls *vp)
Definition: vls.c:111
HIDDEN void comm_error(const char *str)
Definition: fbserv_obj.c:61
int fb_readrect(fb *ifp, int xmin, int ymin, int width, int height, unsigned char *pp)
Definition: fb_generic.c:308
Definition: pkg.h:57
void fbs_rfbscursor(struct pkg_conn *pcp, char *buf)
Definition: fbserv_obj.c:659
Definition: fb.h:82
char * pkc_curpos
current position in pkg_buf
Definition: pkg.h:100
int fb_rmap(fb *ifp, ColorMap *cmap)
Definition: fb_generic.c:280
size_t pkc_len
pkg_len, in host order
Definition: pkg.h:84
int fb_getview(fb *ifp, int *xcenter, int *ycenter, int *xzoom, int *yzoom)
Definition: fb_generic.c:292
void fbs_rfbzoom(struct pkg_conn *pcp, char *buf)
Definition: fbserv_obj.c:703
ssize_t fb_write(fb *ifp, int x, int y, const unsigned char *pp, size_t count)
Definition: fb_generic.c:276
int fb_wmap(fb *ifp, const ColorMap *cmap)
Definition: fb_generic.c:284
unsigned short pkg_gshort(char *buf)
Definition: pkg.c:157
int fb_flush(fb *ifp)
void fbs_rfbgetcursor(struct pkg_conn *pcp, char *buf)
Definition: fbserv_obj.c:609
int fbs_open(struct fbserv_obj *fbsp, int port)
Definition: fbserv_obj.c:983
void fbs_rfbsetcursor(struct pkg_conn *pcp, char *buf)
Definition: fbserv_obj.c:629
void bu_vls_printf(struct bu_vls *vls, const char *fmt,...) _BU_ATTR_PRINTF23
Definition: vls.c:694
unsigned long pkg_glong(char *buf)
Definition: pkg.c:168
int fb_clear(fb *ifp, unsigned char *pp)
Definition: fb_generic.c:268
int pkg_permserver(const char *service, const char *protocol, int backlog, pkg_errlog)
void fbs_rfbreadrect(struct pkg_conn *pcp, char *buf)
Definition: fbserv_obj.c:440
int fb_bwreadrect(fb *ifp, int xmin, int ymin, int width, int height, unsigned char *pp)
Definition: fb_generic.c:316
Definition: pkg.h:79
void fbs_rfbclear(struct pkg_conn *pcp, char *buf)
Definition: fbserv_obj.c:351
int pkg_suckin(struct pkg_conn *)
Definition: pkg.c:1715
void fbs_rfbwrite(struct pkg_conn *pcp, char *buf)
Definition: fbserv_obj.c:413
A frame-buffer IO structure.
Definition: fb_private.h:80
#define BU_VLS_INIT_ZERO
Definition: vls.h:84
int if_width
current values
Definition: fb_private.h:115
void fbs_rfbpoll(struct pkg_conn *pcp, char *buf)
Definition: fbserv_obj.c:845
char * pkc_buf
start of dynamic buf
Definition: pkg.h:99
struct pkg_conn * pkg_getclient(int fd, const struct pkg_switch *switchp, pkg_errlog errlog, int nodelay)
unsigned short cm_blue[256]
Definition: fb.h:85
void fbs_rfbrmap(struct pkg_conn *pcp, char *buf)
Definition: fbserv_obj.c:768
#define GRN
Definition: color.h:40
Definition: vls.h:56
#define MSG_DATA
Definition: ntp.h:34
HIDDEN void new_client_handler(ClientData clientData, Tcl_Channel chan, char *host, int port)
Definition: fbserv_obj.c:935
void fbs_rfbwmap(struct pkg_conn *pcp, char *buf)
Definition: fbserv_obj.c:797
int fb_setcursor(fb *ifp, const unsigned char *bits, int xb, int yb, int xo, int yo)
Definition: fb_generic.c:296
int fb_writerect(fb *ifp, int xmin, int ymin, int width, int height, const unsigned char *pp)
Definition: fb_generic.c:312
ssize_t fb_read(fb *ifp, int x, int y, unsigned char *pp, size_t count)
Definition: fb_generic.c:272
HIDDEN void new_client(struct fbserv_obj *fbsp, struct pkg_conn *pcp, Tcl_Channel chan)
Definition: fbserv_obj.c:204
int fb_poll(fb *ifp)
Definition: fb_generic.c:250
void fbs_rfbwindow(struct pkg_conn *pcp, char *buf)
Definition: fbserv_obj.c:681
#define PKC_ERROR
Definition: pkg.h:104