proto.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "vnc.h"
  10. #define SHORT(p) (((p)[0]<<8)|((p)[1]))
  11. #define LONG(p) ((SHORT(p)<<16)|SHORT(p+2))
  12. uint8_t zero[64];
  13. Vnc*
  14. vncinit(int fd, int cfd, Vnc *v)
  15. {
  16. if(v == nil)
  17. v = mallocz(sizeof(*v), 1);
  18. Binit(&v->in, fd, OREAD);
  19. Binit(&v->out, fd, OWRITE);
  20. v->datafd = fd;
  21. v->ctlfd = cfd;
  22. return v;
  23. }
  24. void
  25. vncterm(Vnc *v)
  26. {
  27. Bterm(&v->out);
  28. Bterm(&v->in);
  29. }
  30. void
  31. vncflush(Vnc *v)
  32. {
  33. if(Bflush(&v->out) < 0){
  34. if(verbose > 1)
  35. fprint(2, "hungup while sending flush: %r\n");
  36. vnchungup(v);
  37. }
  38. }
  39. uint8_t
  40. vncrdchar(Vnc *v)
  41. {
  42. uint8_t buf[1];
  43. vncrdbytes(v, buf, 1);
  44. return buf[0];
  45. }
  46. uint16_t
  47. vncrdshort(Vnc *v)
  48. {
  49. uint8_t buf[2];
  50. vncrdbytes(v, buf, 2);
  51. return SHORT(buf);
  52. }
  53. uint32_t
  54. vncrdlong(Vnc *v)
  55. {
  56. uint8_t buf[4];
  57. vncrdbytes(v, buf, 4);
  58. return LONG(buf);
  59. }
  60. Point
  61. vncrdpoint(Vnc *v)
  62. {
  63. Point p;
  64. p.x = vncrdshort(v);
  65. p.y = vncrdshort(v);
  66. return p;
  67. }
  68. Rectangle
  69. vncrdrect(Vnc *v)
  70. {
  71. Rectangle r;
  72. r.min.x = vncrdshort(v);
  73. r.min.y = vncrdshort(v);
  74. r.max.x = r.min.x + vncrdshort(v);
  75. r.max.y = r.min.y + vncrdshort(v);
  76. return r;
  77. }
  78. Rectangle
  79. vncrdcorect(Vnc *v)
  80. {
  81. Rectangle r;
  82. r.min.x = vncrdchar(v);
  83. r.min.y = vncrdchar(v);
  84. r.max.x = r.min.x + vncrdchar(v);
  85. r.max.y = r.min.y + vncrdchar(v);
  86. return r;
  87. }
  88. void
  89. vncrdbytes(Vnc *v, void *a, int n)
  90. {
  91. if(Bread(&v->in, a, n) != n){
  92. if(verbose > 1)
  93. fprint(2, "hungup while reading\n");
  94. vnchungup(v);
  95. }
  96. }
  97. Pixfmt
  98. vncrdpixfmt(Vnc *v)
  99. {
  100. Pixfmt fmt;
  101. uint8_t pad[3];
  102. fmt.bpp = vncrdchar(v);
  103. fmt.depth = vncrdchar(v);
  104. fmt.bigendian = vncrdchar(v);
  105. fmt.truecolor = vncrdchar(v);
  106. fmt.red.max = vncrdshort(v);
  107. fmt.green.max = vncrdshort(v);
  108. fmt.blue.max = vncrdshort(v);
  109. fmt.red.shift = vncrdchar(v);
  110. fmt.green.shift = vncrdchar(v);
  111. fmt.blue.shift = vncrdchar(v);
  112. vncrdbytes(v, pad, 3);
  113. return fmt;
  114. }
  115. char*
  116. vncrdstring(Vnc *v)
  117. {
  118. uint32_t len;
  119. char *s;
  120. len = vncrdlong(v);
  121. s = malloc(len+1);
  122. assert(s != nil);
  123. vncrdbytes(v, s, len);
  124. s[len] = '\0';
  125. return s;
  126. }
  127. /*
  128. * on the server side of the negotiation protocol, we read
  129. * the client response and then run the negotiated function.
  130. * in some cases (e.g., TLS) the negotiated function needs to
  131. * use v->datafd directly and be sure that no data has been
  132. * buffered away in the Bio. since we know the client is waiting
  133. * for our response, it won't have sent any until we respond.
  134. * thus we read the response with vncrdstringx, which goes
  135. * behind bio's back.
  136. */
  137. char*
  138. vncrdstringx(Vnc *v)
  139. {
  140. char tmp[4];
  141. char *s;
  142. uint32_t len;
  143. assert(Bbuffered(&v->in) == 0);
  144. if(readn(v->datafd, tmp, 4) != 4){
  145. fprint(2, "cannot rdstringx: %r");
  146. vnchungup(v);
  147. }
  148. len = LONG(tmp);
  149. s = malloc(len+1);
  150. assert(s != nil);
  151. if(readn(v->datafd, s, len) != len){
  152. fprint(2, "cannot rdstringx len %lu: %r", len);
  153. vnchungup(v);
  154. }
  155. s[len] = '\0';
  156. return s;
  157. }
  158. void
  159. vncwrstring(Vnc *v, char *s)
  160. {
  161. uint32_t len;
  162. len = strlen(s);
  163. vncwrlong(v, len);
  164. vncwrbytes(v, s, len);
  165. }
  166. void
  167. vncwrbytes(Vnc *v, void *a, int n)
  168. {
  169. if(Bwrite(&v->out, a, n) < 0){
  170. if(verbose > 1)
  171. fprint(2, "hungup while writing bytes\n");
  172. vnchungup(v);
  173. }
  174. }
  175. void
  176. vncwrlong(Vnc *v, uint32_t u)
  177. {
  178. uint8_t buf[4];
  179. buf[0] = u>>24;
  180. buf[1] = u>>16;
  181. buf[2] = u>>8;
  182. buf[3] = u;
  183. vncwrbytes(v, buf, 4);
  184. }
  185. void
  186. vncwrshort(Vnc *v, uint16_t u)
  187. {
  188. uint8_t buf[2];
  189. buf[0] = u>>8;
  190. buf[1] = u;
  191. vncwrbytes(v, buf, 2);
  192. }
  193. void
  194. vncwrchar(Vnc *v, uint8_t c)
  195. {
  196. vncwrbytes(v, &c, 1);
  197. }
  198. void
  199. vncwrpixfmt(Vnc *v, Pixfmt *fmt)
  200. {
  201. vncwrchar(v, fmt->bpp);
  202. vncwrchar(v, fmt->depth);
  203. vncwrchar(v, fmt->bigendian);
  204. vncwrchar(v, fmt->truecolor);
  205. vncwrshort(v, fmt->red.max);
  206. vncwrshort(v, fmt->green.max);
  207. vncwrshort(v, fmt->blue.max);
  208. vncwrchar(v, fmt->red.shift);
  209. vncwrchar(v, fmt->green.shift);
  210. vncwrchar(v, fmt->blue.shift);
  211. vncwrbytes(v, zero, 3);
  212. }
  213. void
  214. vncwrrect(Vnc *v, Rectangle r)
  215. {
  216. vncwrshort(v, r.min.x);
  217. vncwrshort(v, r.min.y);
  218. vncwrshort(v, r.max.x-r.min.x);
  219. vncwrshort(v, r.max.y-r.min.y);
  220. }
  221. void
  222. vncwrpoint(Vnc *v, Point p)
  223. {
  224. vncwrshort(v, p.x);
  225. vncwrshort(v, p.y);
  226. }
  227. void
  228. vnclock(Vnc *v)
  229. {
  230. qlock(&v->qlock);
  231. }
  232. void
  233. vncunlock(Vnc *v)
  234. {
  235. qunlock(&v->qlock);
  236. }
  237. void
  238. hexdump(void *a, int n)
  239. {
  240. uint8_t *p, *ep;
  241. p = a;
  242. ep = p+n;
  243. for(; p<ep; p++)
  244. print("%.2x ", *p);
  245. print("\n");
  246. }
  247. void
  248. vncgobble(Vnc *v, int32_t n)
  249. {
  250. uint8_t buf[8192];
  251. int32_t m;
  252. while(n > 0){
  253. m = n;
  254. if(m > sizeof(buf))
  255. m = sizeof(buf);
  256. vncrdbytes(v, buf, m);
  257. n -= m;
  258. }
  259. }