socket.c 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389
  1. /*
  2. socket.c -- Sockets layer
  3. Copyright (c) All Rights Reserved. See details at the end of the file.
  4. */
  5. /********************************** Includes **********************************/
  6. #include "goahead.h"
  7. /************************************ Locals **********************************/
  8. PUBLIC WebsSocket **socketList; /* List of open sockets */
  9. PUBLIC int socketMax; /* Maximum size of socket */
  10. PUBLIC Socket socketHighestFd = -1; /* Highest socket fd opened */
  11. PUBLIC int socketOpenCount = 0; /* Number of task using sockets */
  12. static int hasIPv6; /* System supports IPv6 */
  13. /***************************** Forward Declarations ***************************/
  14. static int ipv6(char *ip);
  15. static void socketAccept(WebsSocket *sp);
  16. static void socketDoEvent(WebsSocket *sp);
  17. /*********************************** Code *************************************/
  18. PUBLIC int socketOpen()
  19. {
  20. Socket fd;
  21. if (++socketOpenCount > 1) {
  22. return 0;
  23. }
  24. #if ME_WIN_LIKE
  25. {
  26. WSADATA wsaData;
  27. if (WSAStartup(MAKEWORD(1,1), &wsaData) != 0) {
  28. return -1;
  29. }
  30. if (wsaData.wVersion != MAKEWORD(1,1)) {
  31. WSACleanup();
  32. return -1;
  33. }
  34. }
  35. #endif
  36. socketList = NULL;
  37. socketMax = 0;
  38. socketHighestFd = -1;
  39. if ((fd = socket(AF_INET6, SOCK_STREAM, 0)) != -1) {
  40. hasIPv6 = 1;
  41. closesocket(fd);
  42. } else {
  43. trace(1, "This system does not have IPv6 support");
  44. }
  45. return 0;
  46. }
  47. PUBLIC void socketClose()
  48. {
  49. int i;
  50. if (--socketOpenCount <= 0) {
  51. for (i = socketMax; i >= 0; i--) {
  52. if (socketList && socketList[i]) {
  53. socketCloseConnection(i);
  54. }
  55. }
  56. socketOpenCount = 0;
  57. }
  58. }
  59. PUBLIC bool socketHasDualNetworkStack()
  60. {
  61. bool dual;
  62. #if defined(ME_COMPILER_HAS_SINGLE_STACK) || VXWORKS
  63. dual = 0;
  64. #else
  65. dual = hasIPv6;
  66. #endif
  67. return dual;
  68. }
  69. PUBLIC bool socketHasIPv6()
  70. {
  71. return hasIPv6;
  72. }
  73. PUBLIC int socketListen(char *ip, int port, SocketAccept accept, int flags)
  74. {
  75. WebsSocket *sp;
  76. struct sockaddr_storage addr;
  77. Socklen addrlen;
  78. char *sip;
  79. int family, protocol, sid, enable;
  80. if (port > SOCKET_PORT_MAX) {
  81. return -1;
  82. }
  83. if ((sid = socketAlloc(ip, port, accept, flags)) < 0) {
  84. return -1;
  85. }
  86. sp = socketList[sid];
  87. assert(sp);
  88. /*
  89. Change null IP address to be an IPv6 endpoint if the system is dual-stack. That way we can listen on
  90. both IPv4 and IPv6
  91. */
  92. sip = ((ip == 0 || *ip == '\0') && socketHasDualNetworkStack()) ? "::" : ip;
  93. /*
  94. Bind to the socket endpoint and the call listen() to start listening
  95. */
  96. if (socketInfo(sip, port, &family, &protocol, &addr, &addrlen) < 0) {
  97. return -1;
  98. }
  99. if ((sp->sock = socket(family, SOCK_STREAM, protocol)) == SOCKET_ERROR) {
  100. socketFree(sid);
  101. return -1;
  102. }
  103. socketHighestFd = max(socketHighestFd, sp->sock);
  104. #if ME_COMPILER_HAS_FCNTL
  105. fcntl(sp->sock, F_SETFD, FD_CLOEXEC);
  106. #endif
  107. enable = 1;
  108. #if ME_UNIX_LIKE || VXWORKS
  109. if (setsockopt(sp->sock, SOL_SOCKET, SO_REUSEADDR, (char*) &enable, sizeof(enable)) != 0) {
  110. error("Cannot set reuseaddr, errno %d", errno);
  111. }
  112. #if defined(SO_REUSEPORT) && KEEP
  113. /*
  114. This permits multiple servers listening on the same endpoint
  115. */
  116. if (setsockopt(sp->sock, SOL_SOCKET, SO_REUSEPORT, (char*) &enable, sizeof(enable)) != 0) {
  117. error("Cannot set reuseport, errno %d", errno);
  118. }
  119. #endif
  120. #elif ME_WIN_LIKE && defined(SO_EXCLUSIVEADDRUSE)
  121. if (setsockopt(sp->sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char*) &enable, sizeof(enable)) != 0) {
  122. error("Cannot set exclusiveaddruse, errno %d", WSAGetLastError());
  123. }
  124. #endif
  125. #if defined(IPV6_V6ONLY)
  126. /*
  127. By default, most stacks listen on both IPv6 and IPv4 if ip == 0, except windows which inverts this.
  128. So we explicitly control.
  129. */
  130. if (hasIPv6) {
  131. if (ip == 0) {
  132. enable = 0;
  133. setsockopt(sp->sock, IPPROTO_IPV6, IPV6_V6ONLY, (char*) &enable, sizeof(enable));
  134. } else if (ipv6(ip)) {
  135. enable = 1;
  136. setsockopt(sp->sock, IPPROTO_IPV6, IPV6_V6ONLY, (char*) &enable, sizeof(enable));
  137. }
  138. }
  139. #endif
  140. if (bind(sp->sock, (struct sockaddr*) &addr, addrlen) == SOCKET_ERROR) {
  141. error("Cannot bind to address %s:%d, errno %d", ip ? ip : "*", port, errno);
  142. socketFree(sid);
  143. return -1;
  144. }
  145. if (listen(sp->sock, SOMAXCONN) < 0) {
  146. socketFree(sid);
  147. return -1;
  148. }
  149. sp->flags |= SOCKET_LISTENING | SOCKET_NODELAY;
  150. sp->handlerMask |= SOCKET_READABLE;
  151. socketSetBlock(sid, (flags & SOCKET_BLOCK));
  152. if (sp->flags & SOCKET_NODELAY) {
  153. socketSetNoDelay(sid, 1);
  154. }
  155. return sid;
  156. }
  157. #if KEEP
  158. PUBLIC int socketConnect(char *ip, int port, int flags)
  159. {
  160. WebsSocket *sp;
  161. struct sockaddr_storage addr;
  162. socklen_t addrlen;
  163. int family, protocol, sid, rc;
  164. if (port > SOCKET_PORT_MAX) {
  165. return -1;
  166. }
  167. if ((sid = socketAlloc(ip, port, NULL, flags)) < 0) {
  168. return -1;
  169. }
  170. sp = socketList[sid];
  171. assert(sp);
  172. if (socketInfo(ip, port, &family, &protocol, &addr, &addrlen) < 0) {
  173. return -1;
  174. }
  175. if ((sp->sock = socket(AF_INET, SOCK_STREAM, 0)) == SOCKET_ERROR) {
  176. socketFree(sid);
  177. return -1;
  178. }
  179. socketHighestFd = max(socketHighestFd, sp->sock);
  180. #if ME_COMPILER_HAS_FCNTL
  181. fcntl(sp->sock, F_SETFD, FD_CLOEXEC);
  182. #endif
  183. /*
  184. Connect to the remote server in blocking mode, then go into non-blocking mode if desired.
  185. */
  186. if (!(sp->flags & SOCKET_BLOCK)) {
  187. #if ME_WIN_LIKE
  188. /*
  189. Set to non-blocking for an async connect
  190. */
  191. int flag = 1;
  192. if (ioctlsocket(sp->sock, FIONBIO, &flag) == SOCKET_ERROR) {
  193. socketFree(sid);
  194. return -1;
  195. }
  196. sp->flags |= SOCKET_ASYNC;
  197. #else
  198. socketSetBlock(sid, 1);
  199. #endif
  200. }
  201. if ((rc = connect(sp->sock, (struct sockaddr*) &addr, sizeof(addr))) < 0 &&
  202. (rc = tryAlternateConnect(sp->sock, (struct sockaddr*) &addr)) < 0) {
  203. #if ME_WIN_LIKE
  204. if (socketGetError() != EWOULDBLOCK) {
  205. socketFree(sid);
  206. return -1;
  207. }
  208. #else
  209. socketFree(sid);
  210. return -1;
  211. #endif
  212. }
  213. socketSetBlock(sid, (flags & SOCKET_BLOCK));
  214. return sid;
  215. }
  216. /*
  217. If the connection failed, swap the first two bytes in the sockaddr structure. This is a kludge due to a change in
  218. VxWorks between versions 5.3 and 5.4, but we want the product to run on either.
  219. */
  220. static int tryAlternateConnect(int sock, struct sockaddr *sockaddr)
  221. {
  222. #if VXWORKS || TIDSP
  223. char *ptr;
  224. ptr = (char*) sockaddr;
  225. *ptr = *(ptr+1);
  226. *(ptr+1) = 0;
  227. return connect(sock, sockaddr, sizeof(struct sockaddr));
  228. #else
  229. return -1;
  230. #endif
  231. }
  232. #endif
  233. PUBLIC void socketCloseConnection(int sid)
  234. {
  235. WebsSocket *sp;
  236. if ((sp = socketPtr(sid)) == NULL) {
  237. return;
  238. }
  239. socketFree(sid);
  240. }
  241. /*
  242. Accept a connection. Called as a callback on incoming connection.
  243. */
  244. static void socketAccept(WebsSocket *sp)
  245. {
  246. struct sockaddr_storage addrStorage;
  247. struct sockaddr *addr;
  248. WebsSocket *nsp;
  249. Socket newSock;
  250. size_t len;
  251. char ipbuf[1024];
  252. int port, nid;
  253. assert(sp);
  254. /*
  255. Accept the connection and prevent inheriting by children (F_SETFD)
  256. */
  257. len = sizeof(addrStorage);
  258. addr = (struct sockaddr*) &addrStorage;
  259. if ((newSock = accept(sp->sock, addr, (Socklen*) &len)) == SOCKET_ERROR) {
  260. return;
  261. }
  262. #if ME_COMPILER_HAS_FCNTL
  263. fcntl(newSock, F_SETFD, FD_CLOEXEC);
  264. #endif
  265. socketHighestFd = max(socketHighestFd, newSock);
  266. /*
  267. Create a socket structure and insert into the socket list
  268. */
  269. nid = socketAlloc(sp->ip, sp->port, sp->accept, sp->flags);
  270. if ((nsp = socketList[nid]) == 0) {
  271. return;
  272. }
  273. assert(nsp);
  274. nsp->sock = newSock;
  275. nsp->flags &= ~SOCKET_LISTENING;
  276. socketSetBlock(nid, (nsp->flags & SOCKET_BLOCK));
  277. if (nsp->flags & SOCKET_NODELAY) {
  278. socketSetNoDelay(nid, 1);
  279. }
  280. /*
  281. Call the user accept callback. The user must call socketCreateHandler to register for further events of interest.
  282. */
  283. if (sp->accept != NULL) {
  284. /* Get the remote client address */
  285. socketAddress(addr, (int) len, ipbuf, sizeof(ipbuf), &port);
  286. if ((sp->accept)(nid, ipbuf, port, sp->sid) < 0) {
  287. socketFree(nid);
  288. }
  289. }
  290. }
  291. PUBLIC void socketRegisterInterest(int sid, int handlerMask)
  292. {
  293. WebsSocket *sp;
  294. assert(socketPtr(sid));
  295. sp = socketPtr(sid);
  296. sp->handlerMask = handlerMask;
  297. if (sp->flags & SOCKET_BUFFERED_READ) {
  298. sp->handlerMask |= SOCKET_READABLE;
  299. }
  300. if (sp->flags & SOCKET_BUFFERED_WRITE) {
  301. sp->handlerMask |= SOCKET_WRITABLE;
  302. }
  303. }
  304. /*
  305. Wait until an event occurs on a socket. Return zero on success, -1 on failure.
  306. */
  307. PUBLIC int socketWaitForEvent(WebsSocket *sp, int handlerMask)
  308. {
  309. int mask;
  310. assert(sp);
  311. mask = sp->handlerMask;
  312. sp->handlerMask |= handlerMask;
  313. while (socketSelect(sp->sid, 1000)) {
  314. if (sp->currentEvents & (handlerMask | SOCKET_EXCEPTION)) {
  315. break;
  316. }
  317. }
  318. sp->handlerMask = mask;
  319. if (sp->currentEvents & SOCKET_EXCEPTION) {
  320. return -1;
  321. } else if (sp->currentEvents & handlerMask) {
  322. return 0;
  323. }
  324. return 0;
  325. }
  326. PUBLIC void socketHiddenData(WebsSocket *sp, ssize len, int dir)
  327. {
  328. if (len > 0) {
  329. sp->flags |= (dir == SOCKET_READABLE) ? SOCKET_BUFFERED_READ : SOCKET_BUFFERED_WRITE;
  330. if (sp->handler) {
  331. socketReservice(sp->sid);
  332. }
  333. } else {
  334. sp->flags &= ~((dir == SOCKET_READABLE) ? SOCKET_BUFFERED_READ : SOCKET_BUFFERED_WRITE);
  335. }
  336. }
  337. /*
  338. Wait for a handle to become readable or writable and return a number of noticed events. Timeout is in milliseconds.
  339. */
  340. #if ME_WIN_LIKE
  341. PUBLIC int socketSelect(int sid, int timeout)
  342. {
  343. struct timeval tv;
  344. WebsSocket *sp;
  345. fd_set readFds, writeFds, exceptFds;
  346. int nEvents;
  347. int all, socketHighestFd; /* Highest socket fd opened */
  348. FD_ZERO(&readFds);
  349. FD_ZERO(&writeFds);
  350. FD_ZERO(&exceptFds);
  351. socketHighestFd = -1;
  352. tv.tv_sec = (long) (timeout / 1000);
  353. tv.tv_usec = (DWORD) (timeout % 1000) * 1000;
  354. /*
  355. Set the select event masks for events to watch
  356. */
  357. all = nEvents = 0;
  358. if (sid < 0) {
  359. all++;
  360. sid = 0;
  361. }
  362. for (; sid < socketMax; sid++) {
  363. if ((sp = socketList[sid]) == NULL) {
  364. continue;
  365. }
  366. assert(sp);
  367. /*
  368. Set the appropriate bit in the ready masks for the sp->sock.
  369. */
  370. if (sp->handlerMask & SOCKET_READABLE) {
  371. FD_SET(sp->sock, &readFds);
  372. nEvents++;
  373. }
  374. if (sp->handlerMask & SOCKET_WRITABLE) {
  375. FD_SET(sp->sock, &writeFds);
  376. nEvents++;
  377. }
  378. if (sp->handlerMask & SOCKET_EXCEPTION) {
  379. FD_SET(sp->sock, &exceptFds);
  380. nEvents++;
  381. }
  382. if (sp->flags & SOCKET_RESERVICE) {
  383. tv.tv_sec = 0;
  384. tv.tv_usec = 0;
  385. }
  386. if (! all) {
  387. break;
  388. }
  389. }
  390. /*
  391. Windows select() fails if no descriptors are set, instead of just sleeping like other, nice select() calls.
  392. So, if WINDOWS, sleep.
  393. */
  394. if (nEvents == 0) {
  395. Sleep((DWORD) timeout);
  396. return 0;
  397. }
  398. /*
  399. Wait for the event or a timeout
  400. */
  401. nEvents = select(socketHighestFd + 1, &readFds, &writeFds, &exceptFds, &tv);
  402. if (all) {
  403. sid = 0;
  404. }
  405. for (; sid < socketMax; sid++) {
  406. if ((sp = socketList[sid]) == NULL) {
  407. continue;
  408. }
  409. if (sp->flags & SOCKET_RESERVICE) {
  410. if (sp->handlerMask & SOCKET_READABLE) {
  411. sp->currentEvents |= SOCKET_READABLE;
  412. }
  413. if (sp->handlerMask & SOCKET_WRITABLE) {
  414. sp->currentEvents |= SOCKET_WRITABLE;
  415. }
  416. sp->flags &= ~SOCKET_RESERVICE;
  417. nEvents++;
  418. }
  419. if (FD_ISSET(sp->sock, &readFds)) {
  420. sp->currentEvents |= SOCKET_READABLE;
  421. }
  422. if (FD_ISSET(sp->sock, &writeFds)) {
  423. sp->currentEvents |= SOCKET_WRITABLE;
  424. }
  425. if (FD_ISSET(sp->sock, &exceptFds)) {
  426. sp->currentEvents |= SOCKET_EXCEPTION;
  427. }
  428. if (! all) {
  429. break;
  430. }
  431. }
  432. return nEvents;
  433. }
  434. #else /* !ME_WIN_LIKE */
  435. PUBLIC int socketSelect(int sid, int timeout)
  436. {
  437. WebsSocket *sp;
  438. struct timeval tv;
  439. fd_mask *readFds, *writeFds, *exceptFds;
  440. int all, len, nwords, index, bit, nEvents;
  441. /*
  442. Allocate and zero the select masks
  443. */
  444. nwords = (socketHighestFd + NFDBITS) / NFDBITS;
  445. len = nwords * sizeof(fd_mask);
  446. readFds = walloc(len);
  447. memset(readFds, 0, len);
  448. writeFds = walloc(len);
  449. memset(writeFds, 0, len);
  450. exceptFds = walloc(len);
  451. memset(exceptFds, 0, len);
  452. tv.tv_sec = timeout / 1000;
  453. tv.tv_usec = (timeout % 1000) * 1000;
  454. /*
  455. Set the select event masks for events to watch
  456. */
  457. all = nEvents = 0;
  458. if (sid < 0) {
  459. all++;
  460. sid = 0;
  461. }
  462. for (; sid < socketMax; sid++) {
  463. if ((sp = socketList[sid]) == NULL) {
  464. if (all == 0) {
  465. break;
  466. } else {
  467. continue;
  468. }
  469. }
  470. assert(sp);
  471. /*
  472. Initialize the ready masks and compute the mask offsets.
  473. */
  474. index = sp->sock / (NBBY * sizeof(fd_mask));
  475. bit = 1 << (sp->sock % (NBBY * sizeof(fd_mask)));
  476. /*
  477. Set the appropriate bit in the ready masks for the sp->sock.
  478. */
  479. if (sp->handlerMask & SOCKET_READABLE) {
  480. readFds[index] |= bit;
  481. }
  482. if (sp->handlerMask & SOCKET_WRITABLE) {
  483. writeFds[index] |= bit;
  484. }
  485. if (sp->handlerMask & SOCKET_EXCEPTION) {
  486. exceptFds[index] |= bit;
  487. }
  488. if (sp->flags & SOCKET_RESERVICE) {
  489. tv.tv_sec = 0;
  490. tv.tv_usec = 0;
  491. }
  492. if (! all) {
  493. break;
  494. }
  495. }
  496. /*
  497. Wait for the event or a timeout
  498. */
  499. nEvents = select(socketHighestFd + 1, (fd_set *) readFds, (fd_set *) writeFds, (fd_set *) exceptFds, &tv);
  500. if (all) {
  501. sid = 0;
  502. }
  503. for (; sid < socketMax; sid++) {
  504. if ((sp = socketList[sid]) == NULL) {
  505. if (all == 0) {
  506. break;
  507. } else {
  508. continue;
  509. }
  510. }
  511. index = sp->sock / (NBBY * sizeof(fd_mask));
  512. bit = 1 << (sp->sock % (NBBY * sizeof(fd_mask)));
  513. if (sp->flags & SOCKET_RESERVICE) {
  514. if (sp->handlerMask & SOCKET_READABLE) {
  515. sp->currentEvents |= SOCKET_READABLE;
  516. }
  517. if (sp->handlerMask & SOCKET_WRITABLE) {
  518. sp->currentEvents |= SOCKET_WRITABLE;
  519. }
  520. sp->flags &= ~SOCKET_RESERVICE;
  521. nEvents++;
  522. }
  523. if (readFds[index] & bit) {
  524. sp->currentEvents |= SOCKET_READABLE;
  525. }
  526. if (writeFds[index] & bit) {
  527. sp->currentEvents |= SOCKET_WRITABLE;
  528. }
  529. if (exceptFds[index] & bit) {
  530. sp->currentEvents |= SOCKET_EXCEPTION;
  531. }
  532. if (! all) {
  533. break;
  534. }
  535. }
  536. wfree(readFds);
  537. wfree(writeFds);
  538. wfree(exceptFds);
  539. return nEvents;
  540. }
  541. #endif /* WINDOWS || CE */
  542. PUBLIC void socketProcess()
  543. {
  544. WebsSocket *sp;
  545. int sid;
  546. // printf("---> socketProcess\n");
  547. for (sid = 0; sid < socketMax; sid++) {
  548. if ((sp = socketList[sid]) != NULL) {
  549. if (sp->currentEvents & sp->handlerMask) {
  550. socketDoEvent(sp);
  551. }
  552. }
  553. }
  554. }
  555. static void socketDoEvent(WebsSocket *sp)
  556. {
  557. int sid;
  558. assert(sp);
  559. sid = sp->sid;
  560. if (sp->currentEvents & SOCKET_READABLE) {
  561. if (sp->flags & SOCKET_LISTENING) {
  562. socketAccept(sp);
  563. sp->currentEvents = 0;
  564. return;
  565. }
  566. }
  567. /*
  568. Now invoke the users socket handler. NOTE: the handler may delete the
  569. socket, so we must be very careful after calling the handler.
  570. */
  571. if (sp->handler && (sp->handlerMask & sp->currentEvents)) {
  572. (sp->handler)(sid, sp->handlerMask & sp->currentEvents, sp->handler_data);
  573. /*
  574. Make sure socket pointer is still valid, then reset the currentEvents.
  575. */
  576. if (socketList && sid < socketMax && socketList[sid] == sp) {
  577. sp->currentEvents = 0;
  578. }
  579. }
  580. }
  581. /*
  582. Set the socket blocking mode. Return the previous mode.
  583. */
  584. PUBLIC int socketSetBlock(int sid, int on)
  585. {
  586. WebsSocket *sp;
  587. int oldBlock;
  588. if ((sp = socketPtr(sid)) == NULL) {
  589. assert(0);
  590. return 0;
  591. }
  592. oldBlock = (sp->flags & SOCKET_BLOCK);
  593. sp->flags &= ~(SOCKET_BLOCK);
  594. if (on) {
  595. sp->flags |= SOCKET_BLOCK;
  596. }
  597. /*
  598. Put the socket into block / non-blocking mode
  599. */
  600. if (sp->flags & SOCKET_BLOCK) {
  601. #if ME_WIN_LIKE
  602. ulong flag = !on;
  603. ioctlsocket(sp->sock, FIONBIO, &flag);
  604. #elif ECOS
  605. int off;
  606. off = 0;
  607. ioctl(sp->sock, FIONBIO, &off);
  608. #elif VXWORKS
  609. int iflag = !on;
  610. ioctl(sp->sock, FIONBIO, (int) &iflag);
  611. #elif TIDSP
  612. setsockopt((SOCKET)sp->sock, SOL_SOCKET, SO_BLOCKING, &on, sizeof(on));
  613. #else
  614. fcntl(sp->sock, F_SETFL, fcntl(sp->sock, F_GETFL) & ~O_NONBLOCK);
  615. #endif
  616. } else {
  617. #if ME_WIN_LIKE
  618. ulong flag = !on;
  619. int rc = ioctlsocket(sp->sock, FIONBIO, &flag);
  620. rc = rc;
  621. #elif ECOS
  622. int on = 1;
  623. ioctl(sp->sock, FIONBIO, &on);
  624. #elif VXWORKS
  625. int iflag = !on;
  626. ioctl(sp->sock, FIONBIO, (int) &iflag);
  627. #elif TIDSP
  628. setsockopt((SOCKET)sp->sock, SOL_SOCKET, SO_BLOCKING, &on, sizeof(on));
  629. #else
  630. fcntl(sp->sock, F_SETFL, fcntl(sp->sock, F_GETFL) | O_NONBLOCK);
  631. #endif
  632. }
  633. #if MACOSX
  634. /* Prevent SIGPIPE when writing to closed socket on OS X */
  635. int iflag = 1;
  636. setsockopt(sp->sock, SOL_SOCKET, SO_NOSIGPIPE, (void*) &iflag, sizeof(iflag));
  637. #endif
  638. return oldBlock;
  639. }
  640. /*
  641. Set the TCP delay behavior (nagle algorithm)
  642. */
  643. PUBLIC int socketSetNoDelay(int sid, bool on)
  644. {
  645. WebsSocket *sp;
  646. int oldDelay;
  647. if ((sp = socketPtr(sid)) == NULL) {
  648. assert(0);
  649. return 0;
  650. }
  651. oldDelay = sp->flags & SOCKET_NODELAY;
  652. if (on) {
  653. sp->flags |= SOCKET_NODELAY;
  654. } else {
  655. sp->flags &= ~(SOCKET_NODELAY);
  656. }
  657. #if ME_WIN_LIKE
  658. {
  659. BOOL noDelay;
  660. noDelay = on ? 1 : 0;
  661. setsockopt(sp->sock, IPPROTO_TCP, TCP_NODELAY, (FAR char*) &noDelay, sizeof(BOOL));
  662. }
  663. #else
  664. {
  665. int noDelay;
  666. noDelay = on ? 1 : 0;
  667. setsockopt(sp->sock, IPPROTO_TCP, TCP_NODELAY, (char*) &noDelay, sizeof(int));
  668. }
  669. #endif /* ME_WIN_LIKE */
  670. return oldDelay;
  671. }
  672. /*
  673. Write to a socket. Absorb as much data as the socket can buffer. Block if the socket is in blocking mode. Returns -1
  674. on error, otherwise the number of bytes written.
  675. */
  676. PUBLIC ssize socketWrite(int sid, void *buf, ssize bufsize)
  677. {
  678. WebsSocket *sp;
  679. ssize len, written, sofar;
  680. int errCode;
  681. if (buf == 0 || (sp = socketPtr(sid)) == NULL) {
  682. return -1;
  683. }
  684. if (sp->flags & SOCKET_EOF) {
  685. return -1;
  686. }
  687. len = bufsize;
  688. sofar = 0;
  689. while (len > 0) {
  690. if ((written = send(sp->sock, (char*) buf + sofar, (int) len, 0)) < 0) {
  691. errCode = socketGetError();
  692. if (errCode == EINTR) {
  693. continue;
  694. } else if (errCode == EWOULDBLOCK || errCode == EAGAIN) {
  695. if (sofar) {
  696. /*
  697. If some data was written, we mask the EAGAIN for this time. Caller should recall and then
  698. will get a negative return code with EAGAIN.
  699. */
  700. return sofar;
  701. }
  702. }
  703. return -errCode;
  704. }
  705. len -= written;
  706. sofar += written;
  707. }
  708. return sofar;
  709. }
  710. /*
  711. Read from a socket. Return the number of bytes read if successful. This may be less than the requested "bufsize" and
  712. may be zero. This routine may block if the socket is in blocking mode.
  713. Return -1 for errors or EOF. Distinguish between error and EOF via socketEof().
  714. */
  715. PUBLIC ssize socketRead(int sid, void *buf, ssize bufsize)
  716. {
  717. WebsSocket *sp;
  718. ssize bytes;
  719. int errCode;
  720. assert(buf);
  721. assert(bufsize > 0);
  722. if ((sp = socketPtr(sid)) == NULL) {
  723. return -1;
  724. }
  725. if (sp->flags & SOCKET_EOF) {
  726. return -1;
  727. }
  728. if ((bytes = recv(sp->sock, buf, (int) bufsize, 0)) < 0) {
  729. errCode = socketGetError();
  730. if (errCode == EAGAIN || errCode == EWOULDBLOCK) {
  731. bytes = 0;
  732. } else {
  733. /* Conn reset or Some other error */
  734. sp->flags |= SOCKET_EOF;
  735. bytes = -errCode;
  736. }
  737. } else if (bytes == 0) {
  738. sp->flags |= SOCKET_EOF;
  739. bytes = -1;
  740. }
  741. return bytes;
  742. }
  743. /*
  744. Return true if EOF
  745. */
  746. PUBLIC bool socketEof(int sid)
  747. {
  748. WebsSocket *sp;
  749. if ((sp = socketPtr(sid)) == NULL) {
  750. return 1;
  751. }
  752. return sp->flags & SOCKET_EOF;
  753. }
  754. PUBLIC void socketReservice(int sid)
  755. {
  756. WebsSocket *sp;
  757. if ((sp = socketPtr(sid)) == NULL) {
  758. return;
  759. }
  760. sp->flags |= SOCKET_RESERVICE;
  761. }
  762. /*
  763. Create a user handler for this socket. The handler called whenever there
  764. is an event of interest as defined by handlerMask (SOCKET_READABLE, ...)
  765. */
  766. PUBLIC void socketCreateHandler(int sid, int handlerMask, SocketHandler handler, void *data)
  767. {
  768. WebsSocket *sp;
  769. if ((sp = socketPtr(sid)) == NULL) {
  770. return;
  771. }
  772. sp->handler = handler;
  773. sp->handler_data = data;
  774. socketRegisterInterest(sid, handlerMask);
  775. }
  776. PUBLIC void socketDeleteHandler(int sid)
  777. {
  778. WebsSocket *sp;
  779. if ((sp = socketPtr(sid)) == NULL) {
  780. return;
  781. }
  782. sp->handler = NULL;
  783. socketRegisterInterest(sid, 0);
  784. }
  785. /*
  786. Allocate a new socket structure
  787. */
  788. PUBLIC int socketAlloc(char *ip, int port, SocketAccept accept, int flags)
  789. {
  790. WebsSocket *sp;
  791. int sid;
  792. if ((sid = wallocObject(&socketList, &socketMax, sizeof(WebsSocket))) < 0) {
  793. return -1;
  794. }
  795. sp = socketList[sid];
  796. sp->sid = sid;
  797. sp->accept = accept;
  798. sp->port = port;
  799. sp->fileHandle = -1;
  800. sp->saveMask = -1;
  801. if (ip) {
  802. sp->ip = sclone(ip);
  803. }
  804. sp->flags = flags & (SOCKET_BLOCK | SOCKET_LISTENING | SOCKET_NODELAY);
  805. return sid;
  806. }
  807. /*
  808. Free a socket structure
  809. */
  810. PUBLIC void socketFree(int sid)
  811. {
  812. WebsSocket *sp;
  813. char buf[256];
  814. int i;
  815. if ((sp = socketPtr(sid)) == NULL) {
  816. return;
  817. }
  818. /*
  819. To close a socket, remove any registered interests, set it to non-blocking so that the recv which follows won't
  820. block, do a shutdown on it so peers on the other end will receive a FIN, then read any data not yet retrieved
  821. from the receive buffer, and finally close it. If these steps are not all performed RESETs may be sent to the
  822. other end causing problems.
  823. */
  824. socketRegisterInterest(sid, 0);
  825. if (sp->sock >= 0) {
  826. socketSetBlock(sid, 0);
  827. while (recv(sp->sock, buf, sizeof(buf), 0) > 0) {}
  828. if (shutdown(sp->sock, SHUT_RDWR) >= 0) {
  829. while (recv(sp->sock, buf, sizeof(buf), 0) > 0) {}
  830. }
  831. closesocket(sp->sock);
  832. }
  833. wfree(sp->ip);
  834. wfree(sp);
  835. socketMax = wfreeHandle(&socketList, sid);
  836. /*
  837. Calculate the new highest socket number
  838. */
  839. socketHighestFd = -1;
  840. for (i = 0; i < socketMax; i++) {
  841. if ((sp = socketList[i]) == NULL) {
  842. continue;
  843. }
  844. socketHighestFd = max(socketHighestFd, sp->sock);
  845. }
  846. }
  847. /*
  848. Return the socket object reference
  849. */
  850. WebsSocket *socketPtr(int sid)
  851. {
  852. if (sid < 0 || sid >= socketMax || socketList[sid] == NULL) {
  853. assert(NULL);
  854. errno = EBADF;
  855. return NULL;
  856. }
  857. assert(socketList[sid]);
  858. return socketList[sid];
  859. }
  860. /*
  861. Get the operating system error code
  862. */
  863. PUBLIC int socketGetError()
  864. {
  865. #if ME_WIN_LIKE
  866. switch (WSAGetLastError()) {
  867. case WSAEWOULDBLOCK:
  868. return EWOULDBLOCK;
  869. case WSAECONNRESET:
  870. return ECONNRESET;
  871. case WSAENETDOWN:
  872. return ENETDOWN;
  873. case WSAEPROCLIM:
  874. return EAGAIN;
  875. case WSAEINTR:
  876. return EINTR;
  877. default:
  878. return EINVAL;
  879. }
  880. #else
  881. return errno;
  882. #endif
  883. }
  884. PUBLIC void socketSetError(int error)
  885. {
  886. #if ME_WIN_LIKE
  887. SetLastError(error);
  888. #elif ME_UNIX_LIKE || VXWORKS
  889. errno = error;
  890. #endif
  891. }
  892. /*
  893. Return the underlying socket handle
  894. */
  895. PUBLIC Socket socketGetHandle(int sid)
  896. {
  897. WebsSocket *sp;
  898. if ((sp = socketPtr(sid)) == NULL) {
  899. return -1;
  900. }
  901. return sp->sock;
  902. }
  903. /*
  904. Get blocking mode
  905. */
  906. PUBLIC int socketGetBlock(int sid)
  907. {
  908. WebsSocket *sp;
  909. if ((sp = socketPtr(sid)) == NULL) {
  910. assert(0);
  911. return 0;
  912. }
  913. return (sp->flags & SOCKET_BLOCK);
  914. }
  915. PUBLIC int socketGetMode(int sid)
  916. {
  917. WebsSocket *sp;
  918. if ((sp = socketPtr(sid)) == NULL) {
  919. assert(0);
  920. return 0;
  921. }
  922. return sp->flags;
  923. }
  924. PUBLIC void socketSetMode(int sid, int mode)
  925. {
  926. WebsSocket *sp;
  927. if ((sp = socketPtr(sid)) == NULL) {
  928. assert(0);
  929. return;
  930. }
  931. sp->flags = mode;
  932. }
  933. PUBLIC int socketGetPort(int sid)
  934. {
  935. WebsSocket *sp;
  936. if ((sp = socketPtr(sid)) == NULL) {
  937. return -1;
  938. }
  939. return sp->port;
  940. }
  941. #if ME_UNIX_LIKE || WINDOWS
  942. /*
  943. Get a socket address from a host/port combination. If a host provides both IPv4 and IPv6 addresses,
  944. prefer the IPv4 address. This routine uses getaddrinfo.
  945. Caller must free addr.
  946. */
  947. PUBLIC int socketInfo(char *ip, int port, int *family, int *protocol, struct sockaddr_storage *addr, Socklen *addrlen)
  948. {
  949. struct addrinfo hints, *res, *r;
  950. char portBuf[16];
  951. int v6;
  952. assert(addr);
  953. memset((char*) &hints, '\0', sizeof(hints));
  954. /*
  955. Note that IPv6 does not support broadcast, there is no 255.255.255.255 equivalent.
  956. Multicast can be used over a specific link, but the user must provide that address plus %scope_id.
  957. */
  958. if (ip == 0 || ip[0] == '\0') {
  959. ip = 0;
  960. hints.ai_flags |= AI_PASSIVE; /* Bind to 0.0.0.0 and :: */
  961. }
  962. v6 = ipv6(ip);
  963. hints.ai_socktype = SOCK_STREAM;
  964. if (ip) {
  965. hints.ai_family = v6 ? AF_INET6 : AF_INET;
  966. } else {
  967. hints.ai_family = AF_UNSPEC;
  968. }
  969. itosbuf(portBuf, sizeof(portBuf), port, 10);
  970. /*
  971. Try to sleuth the address to avoid duplicate address lookups. Then try IPv4 first then IPv6.
  972. */
  973. res = 0;
  974. if (getaddrinfo(ip, portBuf, &hints, &res) != 0) {
  975. return -1;
  976. }
  977. /*
  978. Prefer IPv4 if IPv6 not requested
  979. */
  980. for (r = res; r; r = r->ai_next) {
  981. if (v6) {
  982. if (r->ai_family == AF_INET6) {
  983. break;
  984. }
  985. } else {
  986. if (r->ai_family == AF_INET) {
  987. break;
  988. }
  989. }
  990. }
  991. if (r == NULL) {
  992. r = res;
  993. }
  994. memset(addr, 0, sizeof(*addr));
  995. memcpy((char*) addr, (char*) r->ai_addr, (int) r->ai_addrlen);
  996. *addrlen = (int) r->ai_addrlen;
  997. *family = r->ai_family;
  998. *protocol = r->ai_protocol;
  999. freeaddrinfo(res);
  1000. return 0;
  1001. }
  1002. #else
  1003. PUBLIC int socketInfo(char *ip, int port, int *family, int *protocol, struct sockaddr_storage *addr, Socklen *addrlen)
  1004. {
  1005. struct sockaddr_in sa;
  1006. memset((char*) &sa, '\0', sizeof(struct sockaddr_in));
  1007. sa.sin_family = AF_INET;
  1008. sa.sin_port = htons((short) (port & 0xFFFF));
  1009. if (ip && *ip) {
  1010. sa.sin_addr.s_addr = inet_addr((char*) ip);
  1011. } else {
  1012. sa.sin_addr.s_addr = INADDR_ANY;
  1013. }
  1014. if (sa.sin_addr.s_addr == INADDR_NONE) {
  1015. #if VXWORKS
  1016. /*
  1017. VxWorks only supports one interface and this code only supports IPv4
  1018. */
  1019. sa.sin_addr.s_addr = (ulong) hostGetByName((char*) ip);
  1020. if (sa.sin_addr.s_addr < 0) {
  1021. assert(0);
  1022. return 0;
  1023. }
  1024. #else
  1025. struct hostent *hostent;
  1026. hostent = gethostbyname2(ip, AF_INET);
  1027. if (hostent == 0) {
  1028. hostent = gethostbyname2(ip, AF_INET6);
  1029. if (hostent == 0) {
  1030. return -1;
  1031. }
  1032. }
  1033. memcpy((char*) &sa.sin_addr, (char*) hostent->h_addr_list[0], (ssize) hostent->h_length);
  1034. #endif
  1035. }
  1036. memcpy((char*) addr, (char*) &sa, sizeof(sa));
  1037. *addrlen = sizeof(struct sockaddr_in);
  1038. *family = sa.sin_family;
  1039. *protocol = 0;
  1040. return 0;
  1041. }
  1042. #endif
  1043. /*
  1044. Return a numerical IP address and port for the given socket info
  1045. */
  1046. PUBLIC int socketAddress(struct sockaddr *addr, int addrlen, char *ip, int ipLen, int *port)
  1047. {
  1048. #if (ME_UNIX_LIKE || ME_WIN_LIKE)
  1049. char service[NI_MAXSERV];
  1050. #if ME_WIN_LIKE || defined(IN6_IS_ADDR_V4MAPPED)
  1051. if (addr->sa_family == AF_INET6) {
  1052. struct sockaddr_in6* addr6 = (struct sockaddr_in6*) addr;
  1053. if (IN6_IS_ADDR_V4MAPPED(&addr6->sin6_addr)) {
  1054. struct sockaddr_in addr4;
  1055. memset(&addr4, 0, sizeof(addr4));
  1056. addr4.sin_family = AF_INET;
  1057. addr4.sin_port = addr6->sin6_port;
  1058. memcpy(&addr4.sin_addr.s_addr, addr6->sin6_addr.s6_addr + 12, sizeof(addr4.sin_addr.s_addr));
  1059. memcpy(addr, &addr4, sizeof(addr4));
  1060. addrlen = sizeof(addr4);
  1061. }
  1062. }
  1063. #endif
  1064. if (getnameinfo(addr, addrlen, ip, ipLen, service, sizeof(service), NI_NUMERICHOST | NI_NUMERICSERV | NI_NOFQDN)) {
  1065. return -1;
  1066. }
  1067. if (port) {
  1068. *port = atoi(service);
  1069. }
  1070. #else
  1071. struct sockaddr_in *sa;
  1072. #if HAVE_NTOA_R
  1073. sa = (struct sockaddr_in*) addr;
  1074. inet_ntoa_r(sa->sin_addr, ip, ipLen);
  1075. #else
  1076. uchar *cp;
  1077. sa = (struct sockaddr_in*) addr;
  1078. cp = (uchar*) &sa->sin_addr;
  1079. fmt(ip, ipLen, "%d.%d.%d.%d", cp[0], cp[1], cp[2], cp[3]);
  1080. #endif
  1081. if (port) {
  1082. *port = ntohs(sa->sin_port);
  1083. }
  1084. #endif
  1085. return 0;
  1086. }
  1087. /*
  1088. Looks like an IPv6 address if it has 2 or more colons
  1089. */
  1090. static int ipv6(char *ip)
  1091. {
  1092. char *cp;
  1093. int colons;
  1094. if (ip == 0 || *ip == 0) {
  1095. /*
  1096. Listening on just a bare port means IPv4 only.
  1097. */
  1098. return 0;
  1099. }
  1100. colons = 0;
  1101. for (cp = (char*) ip; ((*cp != '\0') && (colons < 2)) ; cp++) {
  1102. if (*cp == ':') {
  1103. colons++;
  1104. }
  1105. }
  1106. return colons >= 2;
  1107. }
  1108. /*
  1109. Parse address and return the IP address and port components. Handles ipv4 and ipv6 addresses.
  1110. If the IP portion is absent, *pip is set to null. If the port portion is absent, port is set to the defaultPort.
  1111. If a ":*" port specifier is used, *pport is set to -1;
  1112. When an address contains an ipv6 port it should be written as:
  1113. aaaa:bbbb:cccc:dddd:eeee:ffff:gggg:hhhh:iiii
  1114. or
  1115. [aaaa:bbbb:cccc:dddd:eeee:ffff:gggg:hhhh:iiii]:port
  1116. If supplied an IPv6 address, the backets are stripped in the returned IP address.
  1117. This routine parses any "https://" prefix.
  1118. Caller must free *pip
  1119. */
  1120. PUBLIC int socketParseAddress(char *address, char **pip, int *pport, int *secure, int defaultPort)
  1121. {
  1122. char *ip, *cp;
  1123. ip = 0;
  1124. if (defaultPort < 0) {
  1125. defaultPort = 80;
  1126. }
  1127. *secure = strncmp(address, "https", 5) == 0;
  1128. if ((cp = strstr(address, "://")) != 0) {
  1129. address = &cp[3];
  1130. }
  1131. if (ipv6(address)) {
  1132. /*
  1133. IPv6. If port is present, it will follow a closing bracket ']'
  1134. */
  1135. if ((cp = strchr(address, ']')) != 0) {
  1136. cp++;
  1137. if ((*cp) && (*cp == ':')) {
  1138. *pport = (*++cp == '*') ? -1 : atoi(cp);
  1139. /* Set ipAddr to ipv6 address without brackets */
  1140. ip = sclone(address + 1);
  1141. cp = strchr(ip, ']');
  1142. *cp = '\0';
  1143. } else {
  1144. /* Handles [a:b:c:d:e:f:g:h:i] case (no port)- should not occur */
  1145. ip = sclone(address + 1);
  1146. if ((cp = strchr(ip, ']')) != 0) {
  1147. *cp = '\0';
  1148. }
  1149. if (*ip == '\0') {
  1150. ip = 0;
  1151. }
  1152. /* No port present, use callers default */
  1153. *pport = defaultPort;
  1154. }
  1155. } else {
  1156. /* Handles a:b:c:d:e:f:g:h:i case (no port) */
  1157. ip = sclone(address);
  1158. /* No port present, use callers default */
  1159. *pport = defaultPort;
  1160. }
  1161. } else {
  1162. /*
  1163. ipv4
  1164. */
  1165. ip = sclone(address);
  1166. if ((cp = strchr(ip, ':')) != 0) {
  1167. *cp++ = '\0';
  1168. if (*cp == '*') {
  1169. *pport = -1;
  1170. } else {
  1171. *pport = atoi(cp);
  1172. }
  1173. if (*ip == '*' || *ip == '\0') {
  1174. wfree(ip);
  1175. ip = 0;
  1176. }
  1177. } else if (strchr(ip, '.')) {
  1178. *pport = defaultPort;
  1179. } else {
  1180. if (isdigit((uchar) *ip)) {
  1181. *pport = atoi(ip);
  1182. wfree(ip);
  1183. ip = 0;
  1184. } else {
  1185. /* No port present, use callers default */
  1186. *pport = defaultPort;
  1187. }
  1188. }
  1189. }
  1190. if (pip) {
  1191. *pip = ip;
  1192. } else if (ip) {
  1193. wfree(ip);
  1194. }
  1195. return 0;
  1196. }
  1197. PUBLIC bool socketIsV6(int sid)
  1198. {
  1199. WebsSocket *sp;
  1200. if ((sp = socketPtr(sid)) == NULL) {
  1201. return 0;
  1202. }
  1203. return sp->ip && ipv6(sp->ip);
  1204. }
  1205. PUBLIC bool socketAddressIsV6(char *ip)
  1206. {
  1207. return ip && ipv6(ip);
  1208. }
  1209. PUBLIC WebsSocket **socketGetList()
  1210. {
  1211. return socketList;
  1212. }
  1213. /*
  1214. Copyright (c) Embedthis Software. All Rights Reserved.
  1215. This software is distributed under commercial and open source licenses.
  1216. You may use the Embedthis GoAhead open source license or you may acquire
  1217. a commercial license from Embedthis Software. You agree to be fully bound
  1218. by the terms of either license. Consult the LICENSE.md distributed with
  1219. this software for full details and other copyrights.
  1220. */