| 71 | }; |
| 72 | |
| 73 | void xs_udp_constructor(xsMachine *the) |
| 74 | { |
| 75 | UDP udp; |
| 76 | int port = 0; |
| 77 | int ttl = -1; |
| 78 | struct udp_pcb *skt; |
| 79 | xsSlot *onReadable = builtinGetCallback(the, xsID_onReadable); |
| 80 | |
| 81 | CHECK_NETWORK_SAFE(); |
| 82 | |
| 83 | xsmcVars(1); |
| 84 | |
| 85 | if (xsmcGet(xsVar(0), xsArg(0), xsID_port)) { |
| 86 | port = xsmcToInteger(xsVar(0)); |
| 87 | if ((port < 0) || (port > 65535)) |
| 88 | xsRangeError("invalid port"); |
| 89 | } |
| 90 | |
| 91 | if (xsmcGet(xsVar(0), xsArg(0), xsID_timeToLive)) { |
| 92 | ttl = xsmcToInteger(xsVar(0)); |
| 93 | if ((ttl <= 0) || (ttl > 255)) |
| 94 | xsRangeError("invalid timeToLive"); |
| 95 | } |
| 96 | |
| 97 | builtinInitIO(); |
| 98 | builtinInitializeTarget(the); |
| 99 | if (kIOFormatBuffer != builtinInitializeFormat(the, kIOFormatBuffer)) |
| 100 | xsRangeError("invalid format"); |
| 101 | |
| 102 | skt = udp_new_safe(); |
| 103 | if (!skt) |
| 104 | xsRangeError("no socket"); |
| 105 | |
| 106 | if (udp_bind_safe(skt, IP_ADDR_ANY, port)) { |
| 107 | udp_remove_safe(skt); |
| 108 | xsUnknownError("bind failed"); |
| 109 | } |
| 110 | |
| 111 | udp = c_calloc(1, sizeof(UDPRecord)); |
| 112 | if (!udp) { |
| 113 | udp_remove_safe(skt); |
| 114 | xsRangeError("no memory"); |
| 115 | } |
| 116 | |
| 117 | xsmcSetHostData(xsThis, udp); |
| 118 | udp->skt = skt; |
| 119 | udp->obj = xsThis; |
| 120 | udp->the = the; |
| 121 | xsRemember(udp->obj); |
| 122 | |
| 123 | udp_recv(skt, (udp_recv_fn)udpReceive, udp); |
| 124 | |
| 125 | if (ttl > 0) |
| 126 | skt->ttl = ttl; |
| 127 | |
| 128 | udp->onReadable = onReadable; |
| 129 | |
| 130 | xsSetHostHooks(xsThis, (xsHostHooks *)&xsUDPHooks); |
nothing calls this directly
no test coverage detected