db_sockets.c 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101
  1. /* -*- mode:c; c-file-style:"k&r"; c-basic-offset: 4; tab-width:4; indent-tabs-mode:nil; mode:auto-fill; fill-column:78; -*- */
  2. /* vim: set ts=4 sw=4 et tw=78 fo=cqt wm=0: */
  3. /* Copyright (C) 2014 OSCAR lab, Stony Brook University
  4. This file is part of Graphene Library OS.
  5. Graphene Library OS is free software: you can redistribute it and/or
  6. modify it under the terms of the GNU General Public License
  7. as published by the Free Software Foundation, either version 3 of the
  8. License, or (at your option) any later version.
  9. Graphene Library OS is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  15. /*
  16. * db_socket.c
  17. *
  18. * This file contains operands for streams with URIs that start with
  19. * "tcp:", "tcp.srv:", "udp:", "udp.srv:".
  20. */
  21. #include "pal_defs.h"
  22. #include "pal_linux_defs.h"
  23. #include "pal.h"
  24. #include "pal_internal.h"
  25. #include "pal_linux.h"
  26. #include "pal_debug.h"
  27. #include "pal_security.h"
  28. #include "pal_error.h"
  29. #include "api.h"
  30. #include <linux/types.h>
  31. #include <linux/poll.h>
  32. #include <linux/in.h>
  33. #include <linux/in6.h>
  34. typedef __kernel_pid_t pid_t;
  35. #include <asm/fcntl.h>
  36. #include <asm-generic/socket.h>
  37. /* 96 bytes is the minimal size of buffer to store a IPv4/IPv6
  38. address */
  39. #define PAL_SOCKADDR_SIZE 96
  40. static inline int addr_size (struct sockaddr * addr)
  41. {
  42. switch (addr->sa_family) {
  43. case AF_INET:
  44. return sizeof(struct sockaddr_in);
  45. case AF_INET6:
  46. return sizeof(struct sockaddr_in6);
  47. default:
  48. return 0;
  49. }
  50. }
  51. /* parsing the string of uri, and fill in the socket address structure.
  52. the latest pointer of uri, length of socket address are returned. */
  53. static int inet_parse_uri (char ** uri, struct sockaddr * addr, unsigned int * addrlen)
  54. {
  55. char * tmp = *uri, * end;
  56. char * addr_str = NULL, * port_str;
  57. int af;
  58. void * addr_buf;
  59. int addr_len;
  60. __be16 * port_buf;
  61. int slen;
  62. if (tmp[0] == '[') {
  63. /* for IPv6, the address will be in the form of
  64. "[xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx]:port". */
  65. struct sockaddr_in6 * addr_in6 = (struct sockaddr_in6 *) addr;
  66. slen = sizeof(struct sockaddr_in6);
  67. memset(addr, 0, slen);
  68. end = strchr(tmp + 1, ']');
  69. if (!end || *(end + 1) != ':')
  70. goto inval;
  71. addr_str = tmp + 1;
  72. addr_len = end - tmp - 1;
  73. port_str = end + 2;
  74. for (end = port_str ; *end >= '0' && *end <= '9' ; end++);
  75. addr_in6->sin6_family = af = AF_INET6;
  76. addr_buf = &addr_in6->sin6_addr.s6_addr;
  77. port_buf = &addr_in6->sin6_port;
  78. } else {
  79. /* for IP, the address will be in the form of "x.x.x.x:port". */
  80. struct sockaddr_in * addr_in = (struct sockaddr_in *) addr;
  81. slen = sizeof(struct sockaddr_in);
  82. memset(addr, 0, slen);
  83. end = strchr(tmp, ':');
  84. if (!end)
  85. goto inval;
  86. addr_str = tmp;
  87. addr_len = end - tmp;
  88. port_str = end + 1;
  89. for (end = port_str ; *end >= '0' && *end <= '9' ; end++);
  90. addr_in->sin_family = af = AF_INET;
  91. addr_buf = &addr_in->sin_addr.s_addr;
  92. port_buf = &addr_in->sin_port;
  93. }
  94. if (af == AF_INET) {
  95. if (!inet_pton4(addr_str, addr_len, addr_buf))
  96. goto inval;
  97. } else {
  98. if (!inet_pton6(addr_str, addr_len, addr_buf))
  99. goto inval;
  100. }
  101. *port_buf = __htons(atoi(port_str));
  102. *uri = *end ? end + 1 : NULL;
  103. if (addrlen)
  104. *addrlen = slen;
  105. return 0;
  106. inval:
  107. return -PAL_ERROR_INVAL;
  108. }
  109. /* create the string of uri from the given socket address */
  110. static int inet_create_uri (char * uri, int count, struct sockaddr * addr,
  111. int addrlen)
  112. {
  113. int len = 0;
  114. if (addr->sa_family == AF_INET) {
  115. if (addrlen != sizeof(struct sockaddr_in))
  116. return PAL_ERROR_INVAL;
  117. struct sockaddr_in * addr_in = (struct sockaddr_in *) addr;
  118. char * addr = (char *) &addr_in->sin_addr.s_addr;
  119. /* for IP, the address will be in the form of "x.x.x.x:port". */
  120. len = snprintf(uri, count, "%u.%u.%u.%u:%u",
  121. (unsigned char) addr[0],
  122. (unsigned char) addr[1],
  123. (unsigned char) addr[2],
  124. (unsigned char) addr[3],
  125. __ntohs(addr_in->sin_port));
  126. } else if (addr->sa_family == AF_INET6) {
  127. if (addrlen != sizeof(struct sockaddr_in6))
  128. return PAL_ERROR_INVAL;
  129. struct sockaddr_in6 * addr_in6 = (struct sockaddr_in6 *) addr;
  130. unsigned short * addr = (unsigned short *) &addr_in6->sin6_addr.s6_addr;
  131. /* for IPv6, the address will be in the form of
  132. "[xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx]:port". */
  133. len = snprintf(uri, count, "[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]:%u",
  134. addr[0], addr[1], addr[2], addr[3],
  135. addr[4], addr[5], addr[6], addr[7],
  136. __ntohs(addr_in6->sin6_port));
  137. } else {
  138. return -PAL_ERROR_INVAL;
  139. }
  140. if (len >= count)
  141. return -PAL_ERROR_TOOLONG;
  142. return len;
  143. }
  144. /* parse the uri for a socket stream. The uri might have both binding
  145. address and connecting address, or connecting address only. The form
  146. of uri will be either "bind-addr:bind-port:connect-addr:connect-port"
  147. or "addr:port". */
  148. static int socket_parse_uri (char * uri,
  149. struct sockaddr ** bind_addr, unsigned int * bind_addrlen,
  150. struct sockaddr ** dest_addr, unsigned int * dest_addrlen)
  151. {
  152. int ret;
  153. if (!bind_addr && !dest_addr)
  154. return 0;
  155. if (!uri || !(*uri)) {
  156. if (bind_addr)
  157. *bind_addr = NULL;
  158. if (dest_addr)
  159. *dest_addr = NULL;
  160. return 0;
  161. }
  162. /* at least parse uri once */
  163. if ((ret = inet_parse_uri(&uri, bind_addr ? *bind_addr : *dest_addr,
  164. bind_addr ? bind_addrlen : dest_addrlen)) < 0)
  165. return ret;
  166. if (!(bind_addr && dest_addr))
  167. return 0;
  168. /* if you reach here, it can only be connection address */
  169. if (!uri || (ret = inet_parse_uri(&uri, *dest_addr, dest_addrlen)) < 0) {
  170. *dest_addr = *bind_addr;
  171. *dest_addrlen = *bind_addrlen;
  172. *bind_addr = NULL;
  173. *bind_addrlen = 0;
  174. }
  175. return 0;
  176. }
  177. /* fill in the PAL handle based on the file descriptors and address given. */
  178. static inline
  179. PAL_HANDLE socket_create_handle (int type, int fd, int options,
  180. struct sockaddr * bind_addr,
  181. unsigned int bind_addrlen,
  182. struct sockaddr * dest_addr,
  183. unsigned int dest_addrlen,
  184. struct sockopt * sock_options)
  185. {
  186. PAL_HANDLE hdl = malloc(HANDLE_SIZE(sock) + (bind_addr ? bind_addrlen : 0) +
  187. (dest_addr ? dest_addrlen : 0));
  188. if (!hdl)
  189. return NULL;
  190. memset(hdl, 0, sizeof(union pal_handle));
  191. HANDLE_TYPE(hdl) = type;
  192. HANDLE_HDR(hdl)->flags |= RFD(0)|(type != pal_type_tcpsrv ? WFD(0) : 0);
  193. hdl->sock.fd = fd;
  194. void * addr = (void *) hdl + HANDLE_SIZE(sock);
  195. if (bind_addr) {
  196. hdl->sock.bind = (PAL_PTR) addr;
  197. memcpy(addr, bind_addr, bind_addrlen);
  198. addr += bind_addrlen;
  199. } else {
  200. hdl->sock.bind = (PAL_PTR) NULL;
  201. }
  202. if (dest_addr) {
  203. hdl->sock.conn = (PAL_PTR) addr;
  204. memcpy(addr, dest_addr, dest_addrlen);
  205. addr += dest_addrlen;
  206. } else {
  207. hdl->sock.conn = (PAL_PTR) NULL;
  208. }
  209. hdl->sock.nonblocking = (options & PAL_OPTION_NONBLOCK) ?
  210. PAL_TRUE : PAL_FALSE;
  211. hdl->sock.linger = sock_options->linger;
  212. hdl->sock.receivebuf = sock_options->receivebuf;
  213. hdl->sock.sendbuf = sock_options->sendbuf;
  214. hdl->sock.receivetimeout = sock_options->receivetimeout;
  215. hdl->sock.sendtimeout = sock_options->sendtimeout;
  216. hdl->sock.tcp_cork = sock_options->tcp_cork;
  217. hdl->sock.tcp_keepalive = sock_options->tcp_keepalive;
  218. hdl->sock.tcp_nodelay = sock_options->tcp_nodelay;
  219. return hdl;
  220. }
  221. static int check_zero (void * mem, int size)
  222. {
  223. void * p = mem, * q = mem + size;
  224. while (p < q) {
  225. if (p <= q - sizeof(long)) {
  226. if (*(long *) p)
  227. return 1;
  228. p += sizeof(long);
  229. } else if (p <= q - sizeof(int)) {
  230. if (*(int *) p)
  231. return 1;
  232. p += sizeof(int);
  233. } else if (p <= q - sizeof(short)) {
  234. if (*(short *) p)
  235. return 1;
  236. p += sizeof(short);
  237. } else {
  238. if (*(char *) p)
  239. return 1;
  240. p++;
  241. }
  242. }
  243. return 0;
  244. }
  245. /* check if an address is "Any" */
  246. static int addr_check_any (struct sockaddr * addr)
  247. {
  248. if (addr->sa_family == AF_INET) {
  249. struct sockaddr_in * addr_in =
  250. (struct sockaddr_in *) addr;
  251. return addr_in->sin_port ||
  252. check_zero(&addr_in->sin_addr,
  253. sizeof(addr_in->sin_addr));
  254. } else if (addr->sa_family == AF_INET6) {
  255. struct sockaddr_in6 * addr_in6 =
  256. (struct sockaddr_in6 *) addr;
  257. return addr_in6->sin6_port ||
  258. check_zero(&addr_in6->sin6_addr,
  259. sizeof(addr_in6->sin6_addr));
  260. }
  261. return -PAL_ERROR_NOTSUPPORT;
  262. }
  263. static inline int sock_type (int type, int options)
  264. {
  265. if (options & PAL_OPTION_NONBLOCK)
  266. type |= SOCK_NONBLOCK;
  267. return type;
  268. }
  269. /* listen on a tcp socket */
  270. static int tcp_listen (PAL_HANDLE * handle, char * uri, int options)
  271. {
  272. struct sockaddr buffer, * bind_addr = &buffer;
  273. unsigned int bind_addrlen;
  274. int ret;
  275. if ((ret = socket_parse_uri(uri, &bind_addr, &bind_addrlen,
  276. NULL, NULL)) < 0)
  277. return ret;
  278. /* the socket need to have a binding address, a null address or an
  279. any address is not allowed */
  280. if (!bind_addr || addr_check_any(bind_addr) == 0)
  281. return -PAL_ERROR_INVAL;
  282. struct sockopt sock_options;
  283. ret = ocall_sock_listen(bind_addr->sa_family,
  284. sock_type(SOCK_STREAM, options), 0,
  285. bind_addr, bind_addrlen,
  286. &sock_options);
  287. if (ret < 0)
  288. return ret;
  289. *handle = socket_create_handle(pal_type_tcpsrv, ret, options,
  290. bind_addr, bind_addrlen, NULL, 0,
  291. &sock_options);
  292. if (!(*handle)) {
  293. ocall_close(ret);
  294. return -PAL_ERROR_NOMEM;
  295. }
  296. return 0;
  297. }
  298. /* accept a tcp connection */
  299. static int tcp_accept (PAL_HANDLE handle, PAL_HANDLE * client)
  300. {
  301. if (!IS_HANDLE_TYPE(handle, tcpsrv) ||
  302. !handle->sock.bind || handle->sock.conn)
  303. return -PAL_ERROR_NOTSERVER;
  304. if (handle->sock.fd == PAL_IDX_POISON)
  305. return -PAL_ERROR_BADHANDLE;
  306. struct sockaddr * bind_addr = (struct sockaddr *) handle->sock.bind;
  307. unsigned int bind_addrlen = addr_size(bind_addr);
  308. struct sockaddr dest_addr;
  309. unsigned int dest_addrlen = sizeof(struct sockaddr);
  310. int ret = 0;
  311. struct sockopt sock_options;
  312. ret = ocall_sock_accept(handle->sock.fd, &dest_addr, &dest_addrlen,
  313. &sock_options);
  314. if (ret < 0)
  315. return ret;
  316. *client = socket_create_handle(pal_type_tcp, ret, 0, bind_addr,
  317. bind_addrlen,
  318. &dest_addr, dest_addrlen,
  319. &sock_options);
  320. if (!(*client)) {
  321. ocall_close(ret);
  322. return -PAL_ERROR_NOMEM;
  323. }
  324. return 0;
  325. }
  326. /* connect on a tcp socket */
  327. static int tcp_connect (PAL_HANDLE * handle, char * uri, int options)
  328. {
  329. struct sockaddr buffer[2];
  330. struct sockaddr * bind_addr = buffer, * dest_addr = buffer + 1;
  331. unsigned int bind_addrlen, dest_addrlen;
  332. int ret;
  333. /* accepting two kind of different uri:
  334. dest-ip:dest-port or bind-ip:bind-port:dest-ip:dest-port */
  335. if ((ret = socket_parse_uri(uri, &bind_addr, &bind_addrlen,
  336. &dest_addr, &dest_addrlen)) < 0)
  337. return ret;
  338. if (!dest_addr)
  339. return -PAL_ERROR_INVAL;
  340. if (bind_addr && bind_addr->sa_family != dest_addr->sa_family)
  341. return -PAL_ERROR_INVAL;
  342. struct sockopt sock_options;
  343. ret = ocall_sock_connect(dest_addr->sa_family,
  344. sock_type(SOCK_STREAM, options), 0,
  345. dest_addr, dest_addrlen,
  346. bind_addr, &bind_addrlen, &sock_options);
  347. if (ret < 0)
  348. return ret;
  349. *handle = socket_create_handle(pal_type_tcp, ret, options,
  350. bind_addr, bind_addrlen,
  351. dest_addr, dest_addrlen,
  352. &sock_options);
  353. if (!(*handle)) {
  354. ocall_close(ret);
  355. return -PAL_ERROR_NOMEM;
  356. }
  357. return 0;
  358. }
  359. /* 'open' operation of tcp stream */
  360. static int tcp_open (PAL_HANDLE *handle, const char * type, const char * uri,
  361. int access, int share, int create, int options)
  362. {
  363. int uri_len = strlen(uri) + 1;
  364. if (uri_len > PAL_SOCKADDR_SIZE)
  365. return -PAL_ERROR_TOOLONG;
  366. char uri_buf[PAL_SOCKADDR_SIZE];
  367. memcpy(uri_buf, uri, uri_len);
  368. if (strpartcmp_static(type, "tcp.srv:"))
  369. return tcp_listen(handle, uri_buf, options);
  370. if (strpartcmp_static(type, "tcp:"))
  371. return tcp_connect(handle, uri_buf, options);
  372. return -PAL_ERROR_NOTSUPPORT;
  373. }
  374. /* 'read' operation of tcp stream */
  375. static int tcp_read (PAL_HANDLE handle, int offset, int len, void * buf)
  376. {
  377. if (!IS_HANDLE_TYPE(handle, tcp) || !handle->sock.conn)
  378. return -PAL_ERROR_NOTCONNECTION;
  379. if (handle->sock.fd == PAL_IDX_POISON)
  380. return -PAL_ERROR_ENDOFSTREAM;
  381. int bytes = ocall_sock_recv(handle->sock.fd, buf, len, NULL, NULL);
  382. if (bytes < 0)
  383. return bytes;
  384. if (!bytes)
  385. return -PAL_ERROR_ENDOFSTREAM;
  386. return bytes;
  387. }
  388. /* write' operation of tcp stream */
  389. static int tcp_write (PAL_HANDLE handle, int offset, int len, const void * buf)
  390. {
  391. if (!IS_HANDLE_TYPE(handle, tcp) || !handle->sock.conn)
  392. return -PAL_ERROR_NOTCONNECTION;
  393. if (handle->sock.fd == PAL_IDX_POISON)
  394. return -PAL_ERROR_CONNFAILED;
  395. int bytes = ocall_sock_send(handle->sock.fd, buf, len, NULL, 0);
  396. if (bytes == -PAL_ERROR_TRYAGAIN)
  397. HANDLE_HDR(handle)->flags &= ~WRITEABLE(0);
  398. if (bytes < 0)
  399. return bytes;
  400. if (bytes == len)
  401. HANDLE_HDR(handle)->flags |= WRITEABLE(0);
  402. else
  403. HANDLE_HDR(handle)->flags &= ~WRITEABLE(0);
  404. return bytes;
  405. }
  406. /* used by 'open' operation of tcp stream for bound socket */
  407. static int udp_bind (PAL_HANDLE * handle, char * uri, int options)
  408. {
  409. struct sockaddr buffer, * bind_addr = &buffer;
  410. unsigned int bind_addrlen;
  411. int ret = 0;
  412. if ((ret = socket_parse_uri(uri, &bind_addr, &bind_addrlen,
  413. NULL, NULL)) < 0)
  414. return ret;
  415. assert(bind_addr);
  416. assert(bind_addrlen == addr_size(bind_addr));
  417. struct sockopt sock_options;
  418. ret = ocall_sock_listen(bind_addr->sa_family,
  419. sock_type(SOCK_DGRAM, options), 0,
  420. bind_addr, bind_addrlen, &sock_options);
  421. if (ret < 0)
  422. return ret;
  423. *handle = socket_create_handle(pal_type_udpsrv, ret, options,
  424. bind_addr, bind_addrlen, NULL, 0,
  425. &sock_options);
  426. if (!(*handle)) {
  427. ocall_close(ret);
  428. return -PAL_ERROR_NOMEM;
  429. }
  430. return 0;
  431. }
  432. /* used by 'open' operation of tcp stream for connected socket */
  433. static int udp_connect (PAL_HANDLE * handle, char * uri, int options)
  434. {
  435. struct sockaddr buffer[2];
  436. struct sockaddr * bind_addr = buffer, * dest_addr = buffer + 1;
  437. unsigned int bind_addrlen, dest_addrlen;
  438. int ret;
  439. if ((ret = socket_parse_uri(uri, &bind_addr, &bind_addrlen,
  440. &dest_addr, &dest_addrlen)) < 0)
  441. return ret;
  442. struct sockopt sock_options;
  443. ret = ocall_sock_connect(dest_addr ? dest_addr->sa_family : AF_INET,
  444. sock_type(SOCK_DGRAM, options), 0,
  445. dest_addr, dest_addrlen,
  446. bind_addr, &bind_addrlen, &sock_options);
  447. if (ret < 0)
  448. return ret;
  449. *handle = socket_create_handle(dest_addr ? pal_type_udp :
  450. pal_type_udpsrv, ret, options,
  451. bind_addr, bind_addrlen,
  452. dest_addr, dest_addrlen,
  453. &sock_options);
  454. if (!(*handle)) {
  455. ocall_close(ret);
  456. return -PAL_ERROR_NOMEM;
  457. }
  458. return 0;
  459. }
  460. static int udp_open (PAL_HANDLE *hdl, const char * type, const char * uri,
  461. int access, int share, int create, int options)
  462. {
  463. char buf[PAL_SOCKADDR_SIZE];
  464. int len = strlen(uri);
  465. if (len >= PAL_SOCKADDR_SIZE)
  466. return -PAL_ERROR_TOOLONG;
  467. memcpy(buf, uri, len + 1);
  468. options &= PAL_OPTION_MASK;
  469. if (strpartcmp_static(type, "udp.srv:"))
  470. return udp_bind(hdl, buf, options);
  471. if (strpartcmp_static(type, "udp:"))
  472. return udp_connect(hdl, buf, options);
  473. return -PAL_ERROR_NOTSUPPORT;
  474. }
  475. static int udp_receive (PAL_HANDLE handle, int offset, int len, void * buf)
  476. {
  477. if (!IS_HANDLE_TYPE(handle, udp))
  478. return -PAL_ERROR_NOTCONNECTION;
  479. if (handle->sock.fd == PAL_IDX_POISON)
  480. return -PAL_ERROR_BADHANDLE;
  481. return ocall_sock_recv(handle->sock.fd, buf, len, NULL, NULL);
  482. }
  483. static int udp_receivebyaddr (PAL_HANDLE handle, int offset, int len,
  484. void * buf, char * addr, int addrlen)
  485. {
  486. if (!IS_HANDLE_TYPE(handle, udpsrv))
  487. return -PAL_ERROR_NOTCONNECTION;
  488. if (handle->sock.fd == PAL_IDX_POISON)
  489. return -PAL_ERROR_BADHANDLE;
  490. struct sockaddr conn_addr;
  491. socklen_t conn_addrlen = sizeof(struct sockaddr);
  492. int bytes = ocall_sock_recv(handle->sock.fd, buf, len, &conn_addr,
  493. &conn_addrlen);
  494. if (bytes < 0)
  495. return bytes;
  496. char * addr_uri = strcpy_static(addr, "udp:", addrlen);
  497. if (!addr_uri)
  498. return -PAL_ERROR_OVERFLOW;
  499. int ret = inet_create_uri(addr_uri, addr + addrlen - addr_uri, &conn_addr,
  500. conn_addrlen);
  501. if (ret < 0)
  502. return ret;
  503. return bytes;
  504. }
  505. static int udp_send (PAL_HANDLE handle, int offset, int len, const void * buf)
  506. {
  507. if (!IS_HANDLE_TYPE(handle, udp))
  508. return -PAL_ERROR_NOTCONNECTION;
  509. if (handle->sock.fd == PAL_IDX_POISON)
  510. return -PAL_ERROR_BADHANDLE;
  511. int bytes = ocall_sock_send(handle->sock.fd, buf, len, NULL, 0);
  512. if (bytes == -PAL_ERROR_TRYAGAIN)
  513. HANDLE_HDR(handle)->flags &= ~WRITEABLE(0);
  514. if (bytes < 0)
  515. return bytes;
  516. if (bytes == len)
  517. HANDLE_HDR(handle)->flags |= WRITEABLE(0);
  518. else
  519. HANDLE_HDR(handle)->flags &= ~WRITEABLE(0);
  520. return bytes;
  521. }
  522. static int udp_sendbyaddr (PAL_HANDLE handle, int offset, int len,
  523. const void * buf, const char * addr, int addrlen)
  524. {
  525. if (!IS_HANDLE_TYPE(handle, udpsrv))
  526. return -PAL_ERROR_NOTCONNECTION;
  527. if (handle->sock.fd == PAL_IDX_POISON)
  528. return -PAL_ERROR_BADHANDLE;
  529. if (!strpartcmp_static(addr, "udp:"))
  530. return -PAL_ERROR_INVAL;
  531. addr += static_strlen("udp:");
  532. addrlen -= static_strlen("udp:");
  533. char * addrbuf = __alloca(addrlen);
  534. memcpy(addrbuf, addr, addrlen);
  535. struct sockaddr conn_addr;
  536. unsigned int conn_addrlen = sizeof(struct sockaddr);
  537. int ret = inet_parse_uri(&addrbuf, &conn_addr, &conn_addrlen);
  538. if (ret < 0)
  539. return ret;
  540. int bytes = ocall_sock_send(handle->sock.fd, buf, len, &conn_addr,
  541. conn_addrlen);
  542. if (bytes == -PAL_ERROR_TRYAGAIN)
  543. HANDLE_HDR(handle)->flags &= ~WRITEABLE(0);
  544. if (bytes < 0)
  545. return bytes;
  546. if (bytes == len)
  547. HANDLE_HDR(handle)->flags |= WRITEABLE(0);
  548. else
  549. HANDLE_HDR(handle)->flags &= ~WRITEABLE(0);
  550. return bytes;
  551. }
  552. static int socket_delete (PAL_HANDLE handle, int access)
  553. {
  554. if (handle->sock.fd == PAL_IDX_POISON)
  555. return 0;
  556. if (!IS_HANDLE_TYPE(handle, tcp) && access)
  557. return -PAL_ERROR_INVAL;
  558. if (IS_HANDLE_TYPE(handle, tcp) || IS_HANDLE_TYPE(handle, tcpsrv)) {
  559. int shutdown;
  560. switch (access) {
  561. case 0:
  562. shutdown = SHUT_RDWR;
  563. break;
  564. case PAL_DELETE_RD:
  565. shutdown = SHUT_RD;
  566. break;
  567. case PAL_DELETE_WR:
  568. shutdown = SHUT_WR;
  569. break;
  570. default:
  571. return -PAL_ERROR_INVAL;
  572. }
  573. ocall_sock_shutdown(handle->sock.fd, shutdown);
  574. }
  575. return 0;
  576. }
  577. static int socket_close (PAL_HANDLE handle)
  578. {
  579. if (handle->sock.fd != PAL_IDX_POISON) {
  580. ocall_close(handle->sock.fd);
  581. handle->sock.fd = PAL_IDX_POISON;
  582. }
  583. if (handle->sock.bind)
  584. handle->sock.bind = (PAL_PTR) NULL;
  585. if (handle->sock.conn)
  586. handle->sock.conn = (PAL_PTR) NULL;
  587. return 0;
  588. }
  589. static int socket_attrquerybyhdl (PAL_HANDLE handle, PAL_STREAM_ATTR * attr)
  590. {
  591. if (handle->sock.fd == PAL_IDX_POISON)
  592. return -PAL_ERROR_BADHANDLE;
  593. attr->handle_type = HANDLE_HDR(handle)->type;
  594. attr->disconnected = HANDLE_HDR(handle)->flags & ERROR(0);
  595. attr->nonblocking = handle->sock.nonblocking;
  596. attr->writeable = HANDLE_HDR(handle)->flags & WRITEABLE(0);
  597. attr->pending_size = 0; /* fill in later */
  598. attr->socket.linger = handle->sock.linger;
  599. attr->socket.receivebuf = handle->sock.receivebuf;
  600. attr->socket.sendbuf = handle->sock.sendbuf;
  601. attr->socket.receivetimeout = handle->sock.receivetimeout;
  602. attr->socket.sendtimeout = handle->sock.sendtimeout;
  603. attr->socket.tcp_cork = handle->sock.tcp_cork;
  604. attr->socket.tcp_keepalive = handle->sock.tcp_keepalive;
  605. attr->socket.tcp_nodelay = handle->sock.tcp_nodelay;
  606. int fd = handle->sock.fd, ret;
  607. if (handle->sock.conn) {
  608. /* try use ioctl FIONEAD to get the size of socket */
  609. ret = ocall_fionread(fd);
  610. if (ret < 0)
  611. return ret;
  612. attr->pending_size = ret;
  613. attr->readable = !!attr->pending_size > 0;
  614. } else {
  615. attr->readable = !attr->disconnected;
  616. }
  617. return 0;
  618. }
  619. #ifndef SOL_TCP
  620. # define SOL_TCP 6
  621. #endif
  622. #ifndef TCP_NODELAY
  623. # define TCP_NODELAY 1
  624. #endif
  625. #ifndef TCP_CORK
  626. # define TCP_CORK 3
  627. #endif
  628. static int socket_attrsetbyhdl (PAL_HANDLE handle, PAL_STREAM_ATTR * attr)
  629. {
  630. if (handle->sock.fd == PAL_IDX_POISON)
  631. return -PAL_ERROR_BADHANDLE;
  632. int fd = handle->sock.fd, ret, val;
  633. if (attr->nonblocking != handle->sock.nonblocking) {
  634. ret = ocall_fsetnonblock(fd, attr->nonblocking);
  635. if (ret < 0)
  636. return ret;
  637. handle->sock.nonblocking = attr->nonblocking;
  638. }
  639. if (HANDLE_TYPE(handle) != pal_type_tcpsrv) {
  640. struct __kernel_linger {
  641. int l_onoff;
  642. int l_linger;
  643. };
  644. if (attr->socket.linger != handle->sock.linger) {
  645. struct __kernel_linger l;
  646. l.l_onoff = attr->socket.linger ? 1 : 0;
  647. l.l_linger = attr->socket.linger;
  648. ret = ocall_sock_setopt(fd, SOL_SOCKET, SO_LINGER, &l,
  649. sizeof(struct __kernel_linger));
  650. if (ret < 0)
  651. return ret;
  652. handle->sock.linger = attr->socket.linger;
  653. }
  654. if (attr->socket.receivebuf != handle->sock.receivebuf) {
  655. val = attr->socket.receivebuf;
  656. ret = ocall_sock_setopt(fd, SOL_SOCKET, SO_RCVBUF, &val,
  657. sizeof(int));
  658. if (ret < 0)
  659. return ret;
  660. handle->sock.receivebuf = attr->socket.receivebuf;
  661. }
  662. if (attr->socket.sendbuf != handle->sock.sendbuf) {
  663. val = attr->socket.sendbuf;
  664. ret = ocall_sock_setopt(fd, SOL_SOCKET, SO_SNDBUF,
  665. &val, sizeof(int));
  666. if (ret < 0)
  667. return ret;
  668. handle->sock.sendbuf = attr->socket.sendbuf;
  669. }
  670. if (attr->socket.receivetimeout != handle->sock.receivetimeout) {
  671. val = attr->socket.receivetimeout;
  672. ret = ocall_sock_setopt(fd, SOL_SOCKET, SO_RCVTIMEO,
  673. &val, sizeof(int));
  674. if (ret < 0)
  675. return ret;
  676. handle->sock.receivetimeout = attr->socket.receivetimeout;
  677. }
  678. if (attr->socket.sendtimeout != handle->sock.sendtimeout) {
  679. val = attr->socket.sendtimeout;
  680. ret = ocall_sock_setopt(fd, SOL_SOCKET, SO_SNDTIMEO,
  681. &val, sizeof(int));
  682. if (ret < 0)
  683. return ret;
  684. handle->sock.sendtimeout = attr->socket.sendtimeout;
  685. }
  686. }
  687. if (HANDLE_TYPE(handle) == pal_type_tcp ||
  688. HANDLE_TYPE(handle) == pal_type_tcpsrv) {
  689. if (attr->socket.tcp_cork != handle->sock.tcp_cork) {
  690. val = attr->socket.tcp_cork ? 1 : 0;
  691. ret = ocall_sock_setopt(fd, SOL_TCP, TCP_CORK,
  692. &val, sizeof(int));
  693. if (ret < 0)
  694. return ret;
  695. handle->sock.tcp_cork = attr->socket.tcp_cork;
  696. }
  697. if (attr->socket.tcp_keepalive != handle->sock.tcp_keepalive) {
  698. val = attr->socket.tcp_keepalive ? 1 : 0;
  699. ret = ocall_sock_setopt(fd, SOL_SOCKET, SO_KEEPALIVE,
  700. &val, sizeof(int));
  701. if (ret < 0)
  702. return ret;
  703. handle->sock.tcp_keepalive = attr->socket.tcp_keepalive;
  704. }
  705. if (attr->socket.tcp_nodelay != handle->sock.tcp_nodelay) {
  706. val = attr->socket.tcp_nodelay ? 1 : 0;
  707. ret = ocall_sock_setopt(fd, SOL_TCP, TCP_NODELAY,
  708. &val, sizeof(int));
  709. if (ret < 0)
  710. return ret;
  711. handle->sock.tcp_nodelay = attr->socket.tcp_nodelay;
  712. }
  713. }
  714. return 0;
  715. }
  716. static int socket_getname (PAL_HANDLE handle, char * buffer, int count)
  717. {
  718. int old_count = count;
  719. int ret;
  720. const char * prefix = NULL;
  721. int prefix_len = 0;
  722. struct sockaddr * bind_addr = NULL, * dest_addr = NULL;
  723. switch (HANDLE_TYPE(handle)) {
  724. case pal_type_tcpsrv:
  725. prefix_len = static_strlen("tcp.srv");
  726. prefix = "tcp.srv";
  727. bind_addr = (struct sockaddr *) handle->sock.bind;
  728. break;
  729. case pal_type_tcp:
  730. prefix_len = static_strlen("tcp");
  731. prefix = "tcp";
  732. bind_addr = (struct sockaddr *) handle->sock.bind;
  733. dest_addr = (struct sockaddr *) handle->sock.conn;
  734. break;
  735. case pal_type_udpsrv:
  736. prefix_len = static_strlen("udp.srv");
  737. prefix = "udp.srv";
  738. bind_addr = (struct sockaddr *) handle->sock.bind;
  739. break;
  740. case pal_type_udp:
  741. prefix_len = static_strlen("udp");
  742. prefix = "udp";
  743. bind_addr = (struct sockaddr *) handle->sock.bind;
  744. dest_addr = (struct sockaddr *) handle->sock.conn;
  745. break;
  746. default:
  747. return -PAL_ERROR_INVAL;
  748. }
  749. if (prefix_len >= count)
  750. return -PAL_ERROR_OVERFLOW;
  751. memcpy(buffer, prefix, prefix_len + 1);
  752. buffer += prefix_len;
  753. count -= prefix_len;
  754. for (int i = 0 ; i < 2 ; i++) {
  755. struct sockaddr * addr = i ? dest_addr : bind_addr;
  756. if (addr) {
  757. if (count <= 1)
  758. return -PAL_ERROR_OVERFLOW;
  759. buffer[0] = ':';
  760. buffer[1] = 0;
  761. buffer++;
  762. count--;
  763. if ((ret = inet_create_uri(buffer, count, addr,
  764. addr_size(addr))) < 0)
  765. return ret;
  766. buffer += ret;
  767. count -= ret;
  768. }
  769. }
  770. return old_count - count;
  771. }
  772. struct handle_ops tcp_ops = {
  773. .getname = &socket_getname,
  774. .open = &tcp_open,
  775. .waitforclient = &tcp_accept,
  776. .read = &tcp_read,
  777. .write = &tcp_write,
  778. .delete = &socket_delete,
  779. .close = &socket_close,
  780. .attrquerybyhdl = &socket_attrquerybyhdl,
  781. .attrsetbyhdl = &socket_attrsetbyhdl,
  782. };
  783. struct handle_ops udp_ops = {
  784. .getname = &socket_getname,
  785. .open = &udp_open,
  786. .read = &udp_receive,
  787. .write = &udp_send,
  788. .delete = &socket_delete,
  789. .close = &socket_close,
  790. .attrquerybyhdl = &socket_attrquerybyhdl,
  791. .attrsetbyhdl = &socket_attrsetbyhdl,
  792. };
  793. struct handle_ops udpsrv_ops = {
  794. .getname = &socket_getname,
  795. .open = &udp_open,
  796. .readbyaddr = &udp_receivebyaddr,
  797. .writebyaddr = &udp_sendbyaddr,
  798. .delete = &socket_delete,
  799. .close = &socket_close,
  800. .attrquerybyhdl = &socket_attrquerybyhdl,
  801. .attrsetbyhdl = &socket_attrsetbyhdl,
  802. };
  803. PAL_HANDLE _DkBroadcastStreamOpen (void)
  804. {
  805. PAL_HANDLE hdl = malloc(HANDLE_SIZE(file));
  806. SET_HANDLE_TYPE(hdl, mcast);
  807. HANDLE_HDR(hdl)->flags |= RFD(0)|WFD(1)|WRITEABLE(1);
  808. hdl->mcast.port = pal_sec.mcast_port;
  809. hdl->mcast.srv = pal_sec.mcast_srv;
  810. hdl->mcast.cli = pal_sec.mcast_cli;
  811. return hdl;
  812. }
  813. static int mcast_send (PAL_HANDLE handle, int offset, int size,
  814. const void * buf)
  815. {
  816. if (handle->mcast.srv == PAL_IDX_POISON)
  817. return -PAL_ERROR_BADHANDLE;
  818. int bytes = ocall_sock_send(handle->mcast.srv, buf, size,
  819. NULL, 0);
  820. if (bytes == -PAL_ERROR_TRYAGAIN)
  821. HANDLE_HDR(handle)->flags &= ~WRITEABLE(1);
  822. if (bytes < 0)
  823. return bytes;
  824. if (bytes == size)
  825. HANDLE_HDR(handle)->flags |= WRITEABLE(1);
  826. else
  827. HANDLE_HDR(handle)->flags &= ~WRITEABLE(1);
  828. return bytes;
  829. }
  830. static int mcast_receive (PAL_HANDLE handle, int offset, int size, void * buf)
  831. {
  832. if (handle->mcast.cli == PAL_IDX_POISON)
  833. return -PAL_ERROR_BADHANDLE;
  834. int bytes = ocall_sock_recv(handle->mcast.cli, buf, size, NULL,
  835. NULL);
  836. if (bytes == -PAL_ERROR_TRYAGAIN)
  837. HANDLE_HDR(handle)->flags &= ~WRITEABLE(1);
  838. return bytes;
  839. }
  840. static int mcast_close (PAL_HANDLE handle)
  841. {
  842. if (handle->mcast.srv != PAL_IDX_POISON) {
  843. ocall_close(handle->mcast.srv);
  844. handle->mcast.srv = PAL_IDX_POISON;
  845. }
  846. if (handle->mcast.cli != PAL_IDX_POISON) {
  847. ocall_close(handle->mcast.cli);
  848. handle->mcast.cli = PAL_IDX_POISON;
  849. }
  850. return 0;
  851. }
  852. static int mcast_attrquerybyhdl (PAL_HANDLE handle, PAL_STREAM_ATTR * attr)
  853. {
  854. if (handle->mcast.cli == PAL_IDX_POISON)
  855. return -PAL_ERROR_BADHANDLE;
  856. int ret = ocall_fionread(handle->mcast.cli);
  857. if (ret < 0)
  858. return ret;
  859. memset(attr, 0, sizeof(PAL_STREAM_ATTR));
  860. attr->pending_size = ret;
  861. attr->disconnected = HANDLE_HDR(handle)->flags & (ERROR(0)|ERROR(1));
  862. attr->readable = (attr->pending_size > 0);
  863. attr->writeable = HANDLE_HDR(handle)->flags & WRITEABLE(1);
  864. attr->nonblocking = handle->mcast.nonblocking;
  865. return 0;
  866. }
  867. static int mcast_attrsetbyhdl (PAL_HANDLE handle, PAL_STREAM_ATTR * attr)
  868. {
  869. if (handle->mcast.cli == PAL_IDX_POISON)
  870. return -PAL_ERROR_BADHANDLE;
  871. PAL_BOL * nonblocking = &handle->mcast.nonblocking;
  872. if (attr->nonblocking != *nonblocking) {
  873. int ret = ocall_fsetnonblock(handle->mcast.cli, *nonblocking);
  874. if (ret < 0)
  875. return ret;
  876. *nonblocking = attr->nonblocking;
  877. }
  878. return 0;
  879. }
  880. struct handle_ops mcast_ops = {
  881. .write = &mcast_send,
  882. .read = &mcast_receive,
  883. .close = &mcast_close,
  884. .attrquerybyhdl = &mcast_attrquerybyhdl,
  885. .attrsetbyhdl = &mcast_attrsetbyhdl,
  886. };