00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "rubysocket.h"
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 static VALUE
00027 udp_init(int argc, VALUE *argv, VALUE sock)
00028 {
00029 VALUE arg;
00030 int family = AF_INET;
00031 int fd;
00032
00033 rb_secure(3);
00034 if (rb_scan_args(argc, argv, "01", &arg) == 1) {
00035 family = rsock_family_arg(arg);
00036 }
00037 fd = rsock_socket(family, SOCK_DGRAM, 0);
00038 if (fd < 0) {
00039 rb_sys_fail("socket(2) - udp");
00040 }
00041
00042 return rsock_init_sock(sock, fd);
00043 }
00044
00045 struct udp_arg
00046 {
00047 struct rb_addrinfo *res;
00048 int fd;
00049 };
00050
00051 static VALUE
00052 udp_connect_internal(struct udp_arg *arg)
00053 {
00054 int fd = arg->fd;
00055 struct addrinfo *res;
00056
00057 for (res = arg->res->ai; res; res = res->ai_next) {
00058 if (rsock_connect(fd, res->ai_addr, res->ai_addrlen, 0) >= 0) {
00059 return Qtrue;
00060 }
00061 }
00062 return Qfalse;
00063 }
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081 static VALUE
00082 udp_connect(VALUE sock, VALUE host, VALUE port)
00083 {
00084 rb_io_t *fptr;
00085 struct udp_arg arg;
00086 VALUE ret;
00087
00088 rb_secure(3);
00089 arg.res = rsock_addrinfo(host, port, SOCK_DGRAM, 0);
00090 GetOpenFile(sock, fptr);
00091 arg.fd = fptr->fd;
00092 ret = rb_ensure(udp_connect_internal, (VALUE)&arg,
00093 rsock_freeaddrinfo, (VALUE)arg.res);
00094 if (!ret) rsock_sys_fail_host_port("connect(2)", host, port);
00095 return INT2FIX(0);
00096 }
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110 static VALUE
00111 udp_bind(VALUE sock, VALUE host, VALUE port)
00112 {
00113 rb_io_t *fptr;
00114 struct rb_addrinfo *res0;
00115 struct addrinfo *res;
00116
00117 rb_secure(3);
00118 res0 = rsock_addrinfo(host, port, SOCK_DGRAM, 0);
00119 GetOpenFile(sock, fptr);
00120 for (res = res0->ai; res; res = res->ai_next) {
00121 if (bind(fptr->fd, res->ai_addr, res->ai_addrlen) < 0) {
00122 continue;
00123 }
00124 rb_freeaddrinfo(res0);
00125 return INT2FIX(0);
00126 }
00127 rb_freeaddrinfo(res0);
00128
00129 rsock_sys_fail_host_port("bind(2)", host, port);
00130
00131 return INT2FIX(0);
00132 }
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156 static VALUE
00157 udp_send(int argc, VALUE *argv, VALUE sock)
00158 {
00159 VALUE flags, host, port;
00160 rb_io_t *fptr;
00161 int n;
00162 struct rb_addrinfo *res0;
00163 struct addrinfo *res;
00164 struct rsock_send_arg arg;
00165
00166 if (argc == 2 || argc == 3) {
00167 return rsock_bsock_send(argc, argv, sock);
00168 }
00169 rb_scan_args(argc, argv, "4", &arg.mesg, &flags, &host, &port);
00170
00171 StringValue(arg.mesg);
00172 res0 = rsock_addrinfo(host, port, SOCK_DGRAM, 0);
00173 GetOpenFile(sock, fptr);
00174 arg.fd = fptr->fd;
00175 arg.flags = NUM2INT(flags);
00176 for (res = res0->ai; res; res = res->ai_next) {
00177 retry:
00178 arg.to = res->ai_addr;
00179 arg.tolen = res->ai_addrlen;
00180 rb_thread_fd_writable(arg.fd);
00181 n = (int)BLOCKING_REGION_FD(rsock_sendto_blocking, &arg);
00182 if (n >= 0) {
00183 rb_freeaddrinfo(res0);
00184 return INT2FIX(n);
00185 }
00186 if (rb_io_wait_writable(fptr->fd)) {
00187 goto retry;
00188 }
00189 }
00190 rb_freeaddrinfo(res0);
00191 rsock_sys_fail_host_port("sendto(2)", host, port);
00192 return INT2FIX(n);
00193 }
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244 static VALUE
00245 udp_recvfrom_nonblock(int argc, VALUE *argv, VALUE sock)
00246 {
00247 return rsock_s_recvfrom_nonblock(sock, argc, argv, RECV_IP);
00248 }
00249
00250 void
00251 rsock_init_udpsocket(void)
00252 {
00253
00254
00255
00256
00257
00258
00259 rb_cUDPSocket = rb_define_class("UDPSocket", rb_cIPSocket);
00260 rb_define_method(rb_cUDPSocket, "initialize", udp_init, -1);
00261 rb_define_method(rb_cUDPSocket, "connect", udp_connect, 2);
00262 rb_define_method(rb_cUDPSocket, "bind", udp_bind, 2);
00263 rb_define_method(rb_cUDPSocket, "send", udp_send, -1);
00264 rb_define_method(rb_cUDPSocket, "recvfrom_nonblock", udp_recvfrom_nonblock, -1);
00265 }
00266
00267